summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/classes/Area2D.xml16
-rw-r--r--doc/classes/Area3D.xml16
-rw-r--r--doc/classes/RigidDynamicBody2D.xml8
-rw-r--r--doc/classes/RigidDynamicBody3D.xml8
-rw-r--r--editor/debugger/editor_debugger_node.cpp16
-rw-r--r--editor/debugger/editor_visual_profiler.cpp51
-rw-r--r--editor/editor_help.cpp4
-rw-r--r--editor/editor_themes.cpp8
-rw-r--r--editor/plugins/sprite_2d_editor_plugin.cpp25
-rw-r--r--editor/plugins/sprite_2d_editor_plugin.h1
-rw-r--r--misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj2
-rw-r--r--misc/dist/osx_template.app/Contents/Info.plist2
-rw-r--r--modules/gdscript/gdscript.cpp2
-rw-r--r--modules/gltf/gltf_document.cpp4
-rw-r--r--modules/mono/editor/bindings_generator.cpp437
-rw-r--r--modules/mono/editor/bindings_generator.h8
-rw-r--r--platform/iphone/export/export_plugin.cpp53
-rw-r--r--platform/linuxbsd/display_server_x11.cpp31
-rw-r--r--platform/osx/display_server_osx.h3
-rw-r--r--platform/osx/display_server_osx.mm8
-rw-r--r--platform/osx/export/export_plugin.cpp5
-rw-r--r--platform/osx/godot_window_delegate.mm14
-rw-r--r--platform/osx/os_osx.mm3
-rw-r--r--scene/gui/button.cpp2
-rw-r--r--scene/gui/check_button.cpp5
-rw-r--r--scene/gui/check_button.h2
-rw-r--r--scene/gui/color_picker.cpp3
-rw-r--r--scene/gui/color_picker.h2
-rw-r--r--scene/gui/line_edit.cpp4
-rw-r--r--scene/gui/line_edit.h2
-rw-r--r--scene/gui/link_button.cpp4
-rw-r--r--scene/gui/link_button.h2
-rw-r--r--scene/gui/menu_button.cpp3
-rw-r--r--scene/gui/menu_button.h2
-rw-r--r--scene/gui/option_button.cpp3
-rw-r--r--scene/gui/option_button.h2
-rw-r--r--scene/gui/rich_text_label.cpp4
-rw-r--r--scene/gui/rich_text_label.h2
-rw-r--r--scene/gui/text_edit.cpp10
-rw-r--r--scene/gui/text_edit.h2
40 files changed, 489 insertions, 290 deletions
diff --git a/doc/classes/Area2D.xml b/doc/classes/Area2D.xml
index ed3f873251..1eb74768f5 100644
--- a/doc/classes/Area2D.xml
+++ b/doc/classes/Area2D.xml
@@ -118,8 +118,8 @@
Emitted when one of another Area2D's [Shape2D]s enters one of this Area2D's [Shape2D]s. Requires [member monitoring] to be set to [code]true[/code].
[code]area_rid[/code] the [RID] of the other Area2D's [CollisionObject2D] used by the [PhysicsServer2D].
[code]area[/code] the other Area2D.
- [code]area_shape_index[/code] the index of the [Shape2D] of the other Area2D used by the [PhysicsServer2D]. Get the [CollisionShape2D] node with [code]area.shape_owner_get_owner(area_shape_index)[/code].
- [code]local_shape_index[/code] the index of the [Shape2D] of this Area2D used by the [PhysicsServer2D]. Get the [CollisionShape2D] node with [code]self.shape_owner_get_owner(local_shape_index)[/code].
+ [code]area_shape_index[/code] the index of the [Shape2D] of the other Area2D used by the [PhysicsServer2D]. Get the [CollisionShape2D] node with [code]area.shape_owner_get_owner(area.shape_find_owner(area_shape_index))[/code].
+ [code]local_shape_index[/code] the index of the [Shape2D] of this Area2D used by the [PhysicsServer2D]. Get the [CollisionShape2D] node with [code]self.shape_owner_get_owner(self.shape_find_owner(local_shape_index))[/code].
</description>
</signal>
<signal name="area_shape_exited">
@@ -131,8 +131,8 @@
Emitted when one of another Area2D's [Shape2D]s exits one of this Area2D's [Shape2D]s. Requires [member monitoring] to be set to [code]true[/code].
[code]area_rid[/code] the [RID] of the other Area2D's [CollisionObject2D] used by the [PhysicsServer2D].
[code]area[/code] the other Area2D.
- [code]area_shape_index[/code] the index of the [Shape2D] of the other Area2D used by the [PhysicsServer2D]. Get the [CollisionShape2D] node with [code]area.shape_owner_get_owner(area_shape_index)[/code].
- [code]local_shape_index[/code] the index of the [Shape2D] of this Area2D used by the [PhysicsServer2D]. Get the [CollisionShape2D] node with [code]self.shape_owner_get_owner(local_shape_index)[/code].
+ [code]area_shape_index[/code] the index of the [Shape2D] of the other Area2D used by the [PhysicsServer2D]. Get the [CollisionShape2D] node with [code]area.shape_owner_get_owner(area.shape_find_owner(area_shape_index))[/code].
+ [code]local_shape_index[/code] the index of the [Shape2D] of this Area2D used by the [PhysicsServer2D]. Get the [CollisionShape2D] node with [code]self.shape_owner_get_owner(self.shape_find_owner(local_shape_index))[/code].
</description>
</signal>
<signal name="body_entered">
@@ -158,8 +158,8 @@
Emitted when one of a [PhysicsBody2D] or [TileMap]'s [Shape2D]s enters one of this Area2D's [Shape2D]s. Requires [member monitoring] to be set to [code]true[/code]. [TileMap]s are detected if the [TileSet] has Collision [Shape2D]s.
[code]body_rid[/code] the [RID] of the [PhysicsBody2D] or [TileSet]'s [CollisionObject2D] used by the [PhysicsServer2D].
[code]body[/code] the [Node], if it exists in the tree, of the [PhysicsBody2D] or [TileMap].
- [code]body_shape_index[/code] the index of the [Shape2D] of the [PhysicsBody2D] or [TileMap] used by the [PhysicsServer2D]. Get the [CollisionShape2D] node with [code]body.shape_owner_get_owner(body_shape_index)[/code].
- [code]local_shape_index[/code] the index of the [Shape2D] of this Area2D used by the [PhysicsServer2D]. Get the [CollisionShape2D] node with [code]self.shape_owner_get_owner(local_shape_index)[/code].
+ [code]body_shape_index[/code] the index of the [Shape2D] of the [PhysicsBody2D] or [TileMap] used by the [PhysicsServer2D]. Get the [CollisionShape2D] node with [code]body.shape_owner_get_owner(body.shape_find_owner(body_shape_index))[/code].
+ [code]local_shape_index[/code] the index of the [Shape2D] of this Area2D used by the [PhysicsServer2D]. Get the [CollisionShape2D] node with [code]self.shape_owner_get_owner(self.shape_find_owner(local_shape_index))[/code].
</description>
</signal>
<signal name="body_shape_exited">
@@ -171,8 +171,8 @@
Emitted when one of a [PhysicsBody2D] or [TileMap]'s [Shape2D]s exits one of this Area2D's [Shape2D]s. Requires [member monitoring] to be set to [code]true[/code]. [TileMap]s are detected if the [TileSet] has Collision [Shape2D]s.
[code]body_rid[/code] the [RID] of the [PhysicsBody2D] or [TileSet]'s [CollisionObject2D] used by the [PhysicsServer2D].
[code]body[/code] the [Node], if it exists in the tree, of the [PhysicsBody2D] or [TileMap].
- [code]body_shape_index[/code] the index of the [Shape2D] of the [PhysicsBody2D] or [TileMap] used by the [PhysicsServer2D]. Get the [CollisionShape2D] node with [code]body.shape_owner_get_owner(body_shape_index)[/code].
- [code]local_shape_index[/code] the index of the [Shape2D] of this Area2D used by the [PhysicsServer2D]. Get the [CollisionShape2D] node with [code]self.shape_owner_get_owner(local_shape_index)[/code].
+ [code]body_shape_index[/code] the index of the [Shape2D] of the [PhysicsBody2D] or [TileMap] used by the [PhysicsServer2D]. Get the [CollisionShape2D] node with [code]body.shape_owner_get_owner(body.shape_find_owner(body_shape_index))[/code].
+ [code]local_shape_index[/code] the index of the [Shape2D] of this Area2D used by the [PhysicsServer2D]. Get the [CollisionShape2D] node with [code]self.shape_owner_get_owner(self.shape_find_owner(local_shape_index))[/code].
</description>
</signal>
</signals>
diff --git a/doc/classes/Area3D.xml b/doc/classes/Area3D.xml
index 3d893c1ae4..7d14fd825b 100644
--- a/doc/classes/Area3D.xml
+++ b/doc/classes/Area3D.xml
@@ -137,8 +137,8 @@
Emitted when one of another Area3D's [Shape3D]s enters one of this Area3D's [Shape3D]s. Requires [member monitoring] to be set to [code]true[/code].
[code]area_rid[/code] the [RID] of the other Area3D's [CollisionObject3D] used by the [PhysicsServer3D].
[code]area[/code] the other Area3D.
- [code]area_shape_index[/code] the index of the [Shape3D] of the other Area3D used by the [PhysicsServer3D]. Get the [CollisionShape3D] node with [code]area.shape_owner_get_owner(area_shape_index)[/code].
- [code]local_shape_index[/code] the index of the [Shape3D] of this Area3D used by the [PhysicsServer3D]. Get the [CollisionShape3D] node with [code]self.shape_owner_get_owner(local_shape_index)[/code].
+ [code]area_shape_index[/code] the index of the [Shape3D] of the other Area3D used by the [PhysicsServer3D]. Get the [CollisionShape3D] node with [code]area.shape_owner_get_owner(area.shape_find_owner(area_shape_index))[/code].
+ [code]local_shape_index[/code] the index of the [Shape3D] of this Area3D used by the [PhysicsServer3D]. Get the [CollisionShape3D] node with [code]self.shape_owner_get_owner(self.shape_find_owner(local_shape_index))[/code].
</description>
</signal>
<signal name="area_shape_exited">
@@ -150,8 +150,8 @@
Emitted when one of another Area3D's [Shape3D]s exits one of this Area3D's [Shape3D]s. Requires [member monitoring] to be set to [code]true[/code].
[code]area_rid[/code] the [RID] of the other Area3D's [CollisionObject3D] used by the [PhysicsServer3D].
[code]area[/code] the other Area3D.
- [code]area_shape_index[/code] the index of the [Shape3D] of the other Area3D used by the [PhysicsServer3D]. Get the [CollisionShape3D] node with [code]area.shape_owner_get_owner(area_shape_index)[/code].
- [code]local_shape_index[/code] the index of the [Shape3D] of this Area3D used by the [PhysicsServer3D]. Get the [CollisionShape3D] node with [code]self.shape_owner_get_owner(local_shape_index)[/code].
+ [code]area_shape_index[/code] the index of the [Shape3D] of the other Area3D used by the [PhysicsServer3D]. Get the [CollisionShape3D] node with [code]area.shape_owner_get_owner(area.shape_find_owner(area_shape_index))[/code].
+ [code]local_shape_index[/code] the index of the [Shape3D] of this Area3D used by the [PhysicsServer3D]. Get the [CollisionShape3D] node with [code]self.shape_owner_get_owner(self.shape_find_owner(local_shape_index))[/code].
</description>
</signal>
<signal name="body_entered">
@@ -177,8 +177,8 @@
Emitted when one of a [PhysicsBody3D] or [GridMap]'s [Shape3D]s enters one of this Area3D's [Shape3D]s. Requires [member monitoring] to be set to [code]true[/code]. [GridMap]s are detected if the [MeshLibrary] has Collision [Shape3D]s.
[code]body_rid[/code] the [RID] of the [PhysicsBody3D] or [MeshLibrary]'s [CollisionObject3D] used by the [PhysicsServer3D].
[code]body[/code] the [Node], if it exists in the tree, of the [PhysicsBody3D] or [GridMap].
- [code]body_shape_index[/code] the index of the [Shape3D] of the [PhysicsBody3D] or [GridMap] used by the [PhysicsServer3D]. Get the [CollisionShape3D] node with [code]body.shape_owner_get_owner(body_shape_index)[/code].
- [code]local_shape_index[/code] the index of the [Shape3D] of this Area3D used by the [PhysicsServer3D]. Get the [CollisionShape3D] node with [code]self.shape_owner_get_owner(local_shape_index)[/code].
+ [code]body_shape_index[/code] the index of the [Shape3D] of the [PhysicsBody3D] or [GridMap] used by the [PhysicsServer3D]. Get the [CollisionShape3D] node with [code]body.shape_owner_get_owner(body.shape_find_owner(body_shape_index))[/code].
+ [code]local_shape_index[/code] the index of the [Shape3D] of this Area3D used by the [PhysicsServer3D]. Get the [CollisionShape3D] node with [code]self.shape_owner_get_owner(self.shape_find_owner(local_shape_index))[/code].
</description>
</signal>
<signal name="body_shape_exited">
@@ -190,8 +190,8 @@
Emitted when one of a [PhysicsBody3D] or [GridMap]'s [Shape3D]s enters one of this Area3D's [Shape3D]s. Requires [member monitoring] to be set to [code]true[/code]. [GridMap]s are detected if the [MeshLibrary] has Collision [Shape3D]s.
[code]body_rid[/code] the [RID] of the [PhysicsBody3D] or [MeshLibrary]'s [CollisionObject3D] used by the [PhysicsServer3D].
[code]body[/code] the [Node], if it exists in the tree, of the [PhysicsBody3D] or [GridMap].
- [code]body_shape_index[/code] the index of the [Shape3D] of the [PhysicsBody3D] or [GridMap] used by the [PhysicsServer3D]. Get the [CollisionShape3D] node with [code]body.shape_owner_get_owner(body_shape_index)[/code].
- [code]local_shape_index[/code] the index of the [Shape3D] of this Area3D used by the [PhysicsServer3D]. Get the [CollisionShape3D] node with [code]self.shape_owner_get_owner(local_shape_index)[/code].
+ [code]body_shape_index[/code] the index of the [Shape3D] of the [PhysicsBody3D] or [GridMap] used by the [PhysicsServer3D]. Get the [CollisionShape3D] node with [code]body.shape_owner_get_owner(body.shape_find_owner(body_shape_index))[/code].
+ [code]local_shape_index[/code] the index of the [Shape3D] of this Area3D used by the [PhysicsServer3D]. Get the [CollisionShape3D] node with [code]self.shape_owner_get_owner(self.shape_find_owner(local_shape_index))[/code].
</description>
</signal>
</signals>
diff --git a/doc/classes/RigidDynamicBody2D.xml b/doc/classes/RigidDynamicBody2D.xml
index 696ad7a98e..087156989e 100644
--- a/doc/classes/RigidDynamicBody2D.xml
+++ b/doc/classes/RigidDynamicBody2D.xml
@@ -219,8 +219,8 @@
Emitted when one of this RigidDynamicBody2D's [Shape2D]s collides with another [PhysicsBody2D] or [TileMap]'s [Shape2D]s. Requires [member contact_monitor] to be set to [code]true[/code] and [member contacts_reported] to be set high enough to detect all the collisions. [TileMap]s are detected if the [TileSet] has Collision [Shape2D]s.
[code]body_rid[/code] the [RID] of the other [PhysicsBody2D] or [TileSet]'s [CollisionObject2D] used by the [PhysicsServer2D].
[code]body[/code] the [Node], if it exists in the tree, of the other [PhysicsBody2D] or [TileMap].
- [code]body_shape_index[/code] the index of the [Shape2D] of the other [PhysicsBody2D] or [TileMap] used by the [PhysicsServer2D]. Get the [CollisionShape2D] node with [code]body.shape_owner_get_owner(body_shape_index)[/code].
- [code]local_shape_index[/code] the index of the [Shape2D] of this RigidDynamicBody2D used by the [PhysicsServer2D]. Get the [CollisionShape2D] node with [code]self.shape_owner_get_owner(local_shape_index)[/code].
+ [code]body_shape_index[/code] the index of the [Shape2D] of the other [PhysicsBody2D] or [TileMap] used by the [PhysicsServer2D]. Get the [CollisionShape2D] node with [code]body.shape_owner_get_owner(body.shape_find_owner(body_shape_index))[/code].
+ [code]local_shape_index[/code] the index of the [Shape2D] of this RigidDynamicBody2D used by the [PhysicsServer2D]. Get the [CollisionShape2D] node with [code]self.shape_owner_get_owner(self.shape_find_owner(local_shape_index))[/code].
</description>
</signal>
<signal name="body_shape_exited">
@@ -232,8 +232,8 @@
Emitted when the collision between one of this RigidDynamicBody2D's [Shape2D]s and another [PhysicsBody2D] or [TileMap]'s [Shape2D]s ends. Requires [member contact_monitor] to be set to [code]true[/code] and [member contacts_reported] to be set high enough to detect all the collisions. [TileMap]s are detected if the [TileSet] has Collision [Shape2D]s.
[code]body_rid[/code] the [RID] of the other [PhysicsBody2D] or [TileSet]'s [CollisionObject2D] used by the [PhysicsServer2D].
[code]body[/code] the [Node], if it exists in the tree, of the other [PhysicsBody2D] or [TileMap].
- [code]body_shape_index[/code] the index of the [Shape2D] of the other [PhysicsBody2D] or [TileMap] used by the [PhysicsServer2D]. Get the [CollisionShape2D] node with [code]body.shape_owner_get_owner(body_shape_index)[/code].
- [code]local_shape_index[/code] the index of the [Shape2D] of this RigidDynamicBody2D used by the [PhysicsServer2D]. Get the [CollisionShape2D] node with [code]self.shape_owner_get_owner(local_shape_index)[/code].
+ [code]body_shape_index[/code] the index of the [Shape2D] of the other [PhysicsBody2D] or [TileMap] used by the [PhysicsServer2D]. Get the [CollisionShape2D] node with [code]body.shape_owner_get_owner(body.shape_find_owner(body_shape_index))[/code].
+ [code]local_shape_index[/code] the index of the [Shape2D] of this RigidDynamicBody2D used by the [PhysicsServer2D]. Get the [CollisionShape2D] node with [code]self.shape_owner_get_owner(self.shape_find_owner(local_shape_index))[/code].
</description>
</signal>
<signal name="sleeping_state_changed">
diff --git a/doc/classes/RigidDynamicBody3D.xml b/doc/classes/RigidDynamicBody3D.xml
index 5fd53a7638..85cdcc7f8f 100644
--- a/doc/classes/RigidDynamicBody3D.xml
+++ b/doc/classes/RigidDynamicBody3D.xml
@@ -225,8 +225,8 @@
Emitted when one of this RigidDynamicBody3D's [Shape3D]s collides with another [PhysicsBody3D] or [GridMap]'s [Shape3D]s. Requires [member contact_monitor] to be set to [code]true[/code] and [member contacts_reported] to be set high enough to detect all the collisions. [GridMap]s are detected if the [MeshLibrary] has Collision [Shape3D]s.
[code]body_rid[/code] the [RID] of the other [PhysicsBody3D] or [MeshLibrary]'s [CollisionObject3D] used by the [PhysicsServer3D].
[code]body[/code] the [Node], if it exists in the tree, of the other [PhysicsBody3D] or [GridMap].
- [code]body_shape_index[/code] the index of the [Shape3D] of the other [PhysicsBody3D] or [GridMap] used by the [PhysicsServer3D]. Get the [CollisionShape3D] node with [code]body.shape_owner_get_owner(body_shape_index)[/code].
- [code]local_shape_index[/code] the index of the [Shape3D] of this RigidDynamicBody3D used by the [PhysicsServer3D]. Get the [CollisionShape3D] node with [code]self.shape_owner_get_owner(local_shape_index)[/code].
+ [code]body_shape_index[/code] the index of the [Shape3D] of the other [PhysicsBody3D] or [GridMap] used by the [PhysicsServer3D]. Get the [CollisionShape3D] node with [code]body.shape_owner_get_owner(body.shape_find_owner(body_shape_index))[/code].
+ [code]local_shape_index[/code] the index of the [Shape3D] of this RigidDynamicBody3D used by the [PhysicsServer3D]. Get the [CollisionShape3D] node with [code]self.shape_owner_get_owner(self.shape_find_owner(local_shape_index))[/code].
[b]Note:[/b] Bullet physics cannot identify the shape index when using a [ConcavePolygonShape3D]. Don't use multiple [CollisionShape3D]s when using a [ConcavePolygonShape3D] with Bullet physics if you need shape indices.
</description>
</signal>
@@ -239,8 +239,8 @@
Emitted when the collision between one of this RigidDynamicBody3D's [Shape3D]s and another [PhysicsBody3D] or [GridMap]'s [Shape3D]s ends. Requires [member contact_monitor] to be set to [code]true[/code] and [member contacts_reported] to be set high enough to detect all the collisions. [GridMap]s are detected if the [MeshLibrary] has Collision [Shape3D]s.
[code]body_rid[/code] the [RID] of the other [PhysicsBody3D] or [MeshLibrary]'s [CollisionObject3D] used by the [PhysicsServer3D]. [GridMap]s are detected if the Meshes have [Shape3D]s.
[code]body[/code] the [Node], if it exists in the tree, of the other [PhysicsBody3D] or [GridMap].
- [code]body_shape_index[/code] the index of the [Shape3D] of the other [PhysicsBody3D] or [GridMap] used by the [PhysicsServer3D]. Get the [CollisionShape3D] node with [code]body.shape_owner_get_owner(body_shape_index)[/code].
- [code]local_shape_index[/code] the index of the [Shape3D] of this RigidDynamicBody3D used by the [PhysicsServer3D]. Get the [CollisionShape3D] node with [code]self.shape_owner_get_owner(local_shape_index)[/code].
+ [code]body_shape_index[/code] the index of the [Shape3D] of the other [PhysicsBody3D] or [GridMap] used by the [PhysicsServer3D]. Get the [CollisionShape3D] node with [code]body.shape_owner_get_owner(body.shape_find_owner(body_shape_index))[/code].
+ [code]local_shape_index[/code] the index of the [Shape3D] of this RigidDynamicBody3D used by the [PhysicsServer3D]. Get the [CollisionShape3D] node with [code]self.shape_owner_get_owner(self.shape_find_owner(local_shape_index))[/code].
[b]Note:[/b] Bullet physics cannot identify the shape index when using a [ConcavePolygonShape3D]. Don't use multiple [CollisionShape3D]s when using a [ConcavePolygonShape3D] with Bullet physics if you need shape indices.
</description>
</signal>
diff --git a/editor/debugger/editor_debugger_node.cpp b/editor/debugger/editor_debugger_node.cpp
index a2364b0473..d5a4f5d138 100644
--- a/editor/debugger/editor_debugger_node.cpp
+++ b/editor/debugger/editor_debugger_node.cpp
@@ -39,6 +39,7 @@
#include "editor/scene_tree_dock.h"
#include "scene/gui/menu_button.h"
#include "scene/gui/tab_container.h"
+#include "scene/resources/packed_scene.h"
template <typename Func>
void _for_all(TabContainer *p_node, const Func &p_func) {
@@ -141,11 +142,22 @@ void EditorDebuggerNode::_error_selected(const String &p_file, int p_line, int p
}
void EditorDebuggerNode::_text_editor_stack_goto(const ScriptEditorDebugger *p_debugger) {
- const String file = p_debugger->get_stack_script_file();
+ String file = p_debugger->get_stack_script_file();
if (file.is_empty()) {
return;
}
- stack_script = ResourceLoader::load(file);
+ if (file.is_resource_file()) {
+ stack_script = ResourceLoader::load(file);
+ } else {
+ // If the script is built-in, it can be opened only if the scene is loaded in memory.
+ int i = file.find("::");
+ int j = file.rfind("(", i);
+ if (j > -1) { // If the script is named, the string is "name (file)", so we need to extract the path.
+ file = file.substr(j + 1, file.find(")", i) - j - 1);
+ }
+ Ref<PackedScene> ps = ResourceLoader::load(file.get_slice("::", 0));
+ stack_script = ResourceLoader::load(file);
+ }
const int line = p_debugger->get_stack_script_line() - 1;
emit_signal(SNAME("goto_script_line"), stack_script, line);
emit_signal(SNAME("set_execution"), stack_script, line);
diff --git a/editor/debugger/editor_visual_profiler.cpp b/editor/debugger/editor_visual_profiler.cpp
index 2a1b0029d4..5df86c70fe 100644
--- a/editor/debugger/editor_visual_profiler.cpp
+++ b/editor/debugger/editor_visual_profiler.cpp
@@ -143,12 +143,12 @@ void EditorVisualProfiler::_item_selected() {
}
void EditorVisualProfiler::_update_plot() {
- int w = graph->get_size().width;
- int h = graph->get_size().height;
+ const int w = graph->get_size().width;
+ const int h = graph->get_size().height;
bool reset_texture = false;
- int desired_len = w * h * 4;
+ const int desired_len = w * h * 4;
if (graph_image.size() != desired_len) {
reset_texture = true;
@@ -156,12 +156,13 @@ void EditorVisualProfiler::_update_plot() {
}
uint8_t *wr = graph_image.ptrw();
+ const Color background_color = get_theme_color("dark_color_2", "Editor");
- //clear
+ // Clear the previous frame and set the background color.
for (int i = 0; i < desired_len; i += 4) {
- wr[i + 0] = 0;
- wr[i + 1] = 0;
- wr[i + 2] = 0;
+ wr[i + 0] = Math::fast_ftoi(background_color.r * 255);
+ wr[i + 1] = Math::fast_ftoi(background_color.g * 255);
+ wr[i + 2] = Math::fast_ftoi(background_color.b * 255);
wr[i + 3] = 255;
}
@@ -259,9 +260,9 @@ void EditorVisualProfiler::_update_plot() {
uint8_t r, g, b;
if (column_cpu[j].a == 0) {
- r = 0;
- g = 0;
- b = 0;
+ r = Math::fast_ftoi(background_color.r * 255);
+ g = Math::fast_ftoi(background_color.g * 255);
+ b = Math::fast_ftoi(background_color.b * 255);
} else {
r = CLAMP((column_cpu[j].r / column_cpu[j].a) * 255.0, 0, 255);
g = CLAMP((column_cpu[j].g / column_cpu[j].a) * 255.0, 0, 255);
@@ -279,9 +280,9 @@ void EditorVisualProfiler::_update_plot() {
uint8_t r, g, b;
if (column_gpu[j].a == 0) {
- r = 0;
- g = 0;
- b = 0;
+ r = Math::fast_ftoi(background_color.r * 255);
+ g = Math::fast_ftoi(background_color.g * 255);
+ b = Math::fast_ftoi(background_color.b * 255);
} else {
r = CLAMP((column_gpu[j].r / column_gpu[j].a) * 255.0, 0, 255);
g = CLAMP((column_gpu[j].g / column_gpu[j].a) * 255.0, 0, 255);
@@ -440,8 +441,11 @@ void EditorVisualProfiler::_graph_tex_draw() {
if (last_metric < 0) {
return;
}
+
Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
+ const Color color = get_theme_color(SNAME("font_color"), SNAME("Editor"));
+
if (seeking) {
int max_frames = frame_metrics.size();
int frame = cursor_metric_edit->get_value() - (frame_metrics[last_metric].frame_number - max_frames + 1);
@@ -451,10 +455,9 @@ void EditorVisualProfiler::_graph_tex_draw() {
int half_width = graph->get_size().x / 2;
int cur_x = frame * half_width / max_frames;
- //cur_x /= 2.0;
- graph->draw_line(Vector2(cur_x, 0), Vector2(cur_x, graph->get_size().y), Color(1, 1, 1, 0.8));
- graph->draw_line(Vector2(cur_x + half_width, 0), Vector2(cur_x + half_width, graph->get_size().y), Color(1, 1, 1, 0.8));
+ graph->draw_line(Vector2(cur_x, 0), Vector2(cur_x, graph->get_size().y), color * Color(1, 1, 1));
+ graph->draw_line(Vector2(cur_x + half_width, 0), Vector2(cur_x + half_width, graph->get_size().y), color * Color(1, 1, 1));
}
if (graph_height_cpu > 0) {
@@ -462,10 +465,10 @@ void EditorVisualProfiler::_graph_tex_draw() {
int half_width = graph->get_size().x / 2;
- graph->draw_line(Vector2(0, frame_y), Vector2(half_width, frame_y), Color(1, 1, 1, 0.3));
+ graph->draw_line(Vector2(0, frame_y), Vector2(half_width, frame_y), color * Color(1, 1, 1, 0.5));
- String limit_str = String::num(graph_limit, 2);
- graph->draw_string(font, Vector2(half_width - font->get_string_size(limit_str, font_size).x - 2, frame_y - 2), limit_str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, Color(1, 1, 1, 0.6));
+ const String limit_str = String::num(graph_limit, 2) + " ms";
+ graph->draw_string(font, Vector2(half_width - font->get_string_size(limit_str, font_size).x - 2, frame_y - 2), limit_str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, color * Color(1, 1, 1, 0.75));
}
if (graph_height_gpu > 0) {
@@ -473,14 +476,14 @@ void EditorVisualProfiler::_graph_tex_draw() {
int half_width = graph->get_size().x / 2;
- graph->draw_line(Vector2(half_width, frame_y), Vector2(graph->get_size().x, frame_y), Color(1, 1, 1, 0.3));
+ graph->draw_line(Vector2(half_width, frame_y), Vector2(graph->get_size().x, frame_y), color * Color(1, 1, 1, 0.5));
- String limit_str = String::num(graph_limit, 2);
- graph->draw_string(font, Vector2(half_width * 2 - font->get_string_size(limit_str, font_size).x - 2, frame_y - 2), limit_str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, Color(1, 1, 1, 0.6));
+ const String limit_str = String::num(graph_limit, 2) + " ms";
+ graph->draw_string(font, Vector2(half_width * 2 - font->get_string_size(limit_str, font_size).x - 2, frame_y - 2), limit_str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, color * Color(1, 1, 1, 0.75));
}
- graph->draw_string(font, Vector2(font->get_string_size("X", font_size).x, font->get_ascent(font_size) + 2), "CPU:", HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, Color(1, 1, 1, 0.8));
- graph->draw_string(font, Vector2(font->get_string_size("X", font_size).x + graph->get_size().width / 2, font->get_ascent(font_size) + 2), "GPU:", HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, Color(1, 1, 1, 0.8));
+ graph->draw_string(font, Vector2(font->get_string_size("X", font_size).x, font->get_ascent(font_size) + 2), "CPU:", HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, color * Color(1, 1, 1));
+ graph->draw_string(font, Vector2(font->get_string_size("X", font_size).x + graph->get_size().width / 2, font->get_ascent(font_size) + 2), "GPU:", HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, color * Color(1, 1, 1));
}
void EditorVisualProfiler::_graph_tex_mouse_exit() {
diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp
index fe39f7acc9..39c8509148 100644
--- a/editor/editor_help.cpp
+++ b/editor/editor_help.cpp
@@ -477,9 +477,9 @@ void EditorHelp::_update_method_descriptions(const DocData::ClassDoc p_classdoc,
class_desc->add_text(" ");
class_desc->push_color(comment_color);
if (p_classdoc.is_script_doc) {
- class_desc->append_text(TTR("There is currently no description for this " + p_method_type + "."));
+ class_desc->append_text(vformat(TTR("There is currently no description for this %s."), p_method_type));
} else {
- class_desc->append_text(TTR("There is currently no description for this " + p_method_type + ". Please help us by [color=$color][url=$url]contributing one[/url][/color]!").replace("$url", CONTRIBUTE_URL).replace("$color", link_color_text));
+ class_desc->append_text(vformat(TTR("There is currently no description for this %s. Please help us by [color=$color][url=$url]contributing one[/url][/color]!"), p_method_type).replace("$url", CONTRIBUTE_URL).replace("$color", link_color_text));
}
class_desc->pop();
}
diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp
index 05aa638a4b..cdf51dda20 100644
--- a/editor/editor_themes.cpp
+++ b/editor/editor_themes.cpp
@@ -411,9 +411,11 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
// Colors
bool dark_theme = EditorSettings::get_singleton()->is_dark_theme();
- const Color dark_color_1 = base_color.lerp(Color(0, 0, 0, 1), contrast);
- const Color dark_color_2 = base_color.lerp(Color(0, 0, 0, 1), contrast * 1.5);
- const Color dark_color_3 = base_color.lerp(Color(0, 0, 0, 1), contrast * 2);
+ // Ensure base colors are in the 0..1 luminance range to avoid 8-bit integer overflow or text rendering issues.
+ // Some places in the editor use 8-bit integer colors.
+ const Color dark_color_1 = base_color.lerp(Color(0, 0, 0, 1), contrast).clamp();
+ const Color dark_color_2 = base_color.lerp(Color(0, 0, 0, 1), contrast * 1.5).clamp();
+ const Color dark_color_3 = base_color.lerp(Color(0, 0, 0, 1), contrast * 2).clamp();
const Color background_color = dark_color_2;
diff --git a/editor/plugins/sprite_2d_editor_plugin.cpp b/editor/plugins/sprite_2d_editor_plugin.cpp
index 3489ac2c1e..6a63875324 100644
--- a/editor/plugins/sprite_2d_editor_plugin.cpp
+++ b/editor/plugins/sprite_2d_editor_plugin.cpp
@@ -122,8 +122,8 @@ void Sprite2DEditor::_menu_option(int p_option) {
switch (p_option) {
case MENU_OPTION_CONVERT_TO_MESH_2D: {
- debug_uv_dialog->get_ok_button()->set_text(TTR("Create Mesh2D"));
- debug_uv_dialog->set_title(TTR("Mesh2D Preview"));
+ debug_uv_dialog->get_ok_button()->set_text(TTR("Create MeshInstance2D"));
+ debug_uv_dialog->set_title(TTR("MeshInstance2D Preview"));
_update_mesh_data();
debug_uv_dialog->popup_centered();
@@ -338,7 +338,7 @@ void Sprite2DEditor::_convert_to_mesh_2d_node() {
mesh_instance->set_mesh(mesh);
UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
- ur->create_action(TTR("Convert to Mesh2D"));
+ ur->create_action(TTR("Convert to MeshInstance2D"));
ur->add_do_method(SceneTreeDock::get_singleton(), "replace_node", node, mesh_instance, true, false);
ur->add_do_reference(mesh_instance);
ur->add_undo_method(SceneTreeDock::get_singleton(), "replace_node", mesh_instance, node, false, false);
@@ -498,6 +498,20 @@ void Sprite2DEditor::_debug_uv_draw() {
}
}
+void Sprite2DEditor::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE:
+ case NOTIFICATION_THEME_CHANGED: {
+ options->set_icon(get_theme_icon(SNAME("Sprite2D"), SNAME("EditorIcons")));
+
+ options->get_popup()->set_item_icon(MENU_OPTION_CONVERT_TO_MESH_2D, get_theme_icon(SNAME("MeshInstance2D"), SNAME("EditorIcons")));
+ options->get_popup()->set_item_icon(MENU_OPTION_CONVERT_TO_POLYGON_2D, get_theme_icon(SNAME("Polygon2D"), SNAME("EditorIcons")));
+ options->get_popup()->set_item_icon(MENU_OPTION_CREATE_COLLISION_POLY_2D, get_theme_icon(SNAME("CollisionPolygon2D"), SNAME("EditorIcons")));
+ options->get_popup()->set_item_icon(MENU_OPTION_CREATE_LIGHT_OCCLUDER_2D, get_theme_icon(SNAME("LightOccluder2D"), SNAME("EditorIcons")));
+ } break;
+ }
+}
+
void Sprite2DEditor::_bind_methods() {
ClassDB::bind_method("_add_as_sibling_or_child", &Sprite2DEditor::_add_as_sibling_or_child);
}
@@ -508,9 +522,8 @@ Sprite2DEditor::Sprite2DEditor() {
CanvasItemEditor::get_singleton()->add_control_to_menu_panel(options);
options->set_text(TTR("Sprite2D"));
- options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Sprite2D"), SNAME("EditorIcons")));
- options->get_popup()->add_item(TTR("Convert to Mesh2D"), MENU_OPTION_CONVERT_TO_MESH_2D);
+ options->get_popup()->add_item(TTR("Convert to MeshInstance2D"), MENU_OPTION_CONVERT_TO_MESH_2D);
options->get_popup()->add_item(TTR("Convert to Polygon2D"), MENU_OPTION_CONVERT_TO_POLYGON_2D);
options->get_popup()->add_item(TTR("Create CollisionPolygon2D Sibling"), MENU_OPTION_CREATE_COLLISION_POLY_2D);
options->get_popup()->add_item(TTR("Create LightOccluder2D Sibling"), MENU_OPTION_CREATE_LIGHT_OCCLUDER_2D);
@@ -522,8 +535,6 @@ Sprite2DEditor::Sprite2DEditor() {
add_child(err_dialog);
debug_uv_dialog = memnew(ConfirmationDialog);
- debug_uv_dialog->get_ok_button()->set_text(TTR("Create Mesh2D"));
- debug_uv_dialog->set_title(TTR("Mesh 2D Preview"));
VBoxContainer *vb = memnew(VBoxContainer);
debug_uv_dialog->add_child(vb);
ScrollContainer *scroll = memnew(ScrollContainer);
diff --git a/editor/plugins/sprite_2d_editor_plugin.h b/editor/plugins/sprite_2d_editor_plugin.h
index 3e4cc17cdd..46953b0937 100644
--- a/editor/plugins/sprite_2d_editor_plugin.h
+++ b/editor/plugins/sprite_2d_editor_plugin.h
@@ -87,6 +87,7 @@ class Sprite2DEditor : public Control {
protected:
void _node_removed(Node *p_node);
+ void _notification(int p_what);
static void _bind_methods();
public:
diff --git a/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj b/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj
index e2505de3bf..69899cbe8d 100644
--- a/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj
+++ b/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj
@@ -45,6 +45,7 @@
D0BCFE3418AEBDA2004A7AAE /* $binary.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "$binary.app"; sourceTree = BUILT_PRODUCTS_DIR; };
D0BCFE4318AEBDA2004A7AAE /* $binary-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "$binary-Info.plist"; sourceTree = "<group>"; };
D0BCFE4518AEBDA2004A7AAE /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
+ $pbx_locale_file_reference
D0BCFE7718AEBFEB004A7AAE /* $binary.pck */ = {isa = PBXFileReference; lastKnownFileType = file; path = "$binary.pck"; sourceTree = "<group>"; };
$pbx_launch_screen_file_reference
/* End PBXFileReference section */
@@ -207,6 +208,7 @@
isa = PBXVariantGroup;
children = (
D0BCFE4518AEBDA2004A7AAE /* en */,
+ $pbx_locale_build_reference
);
name = InfoPlist.strings;
sourceTree = "<group>";
diff --git a/misc/dist/osx_template.app/Contents/Info.plist b/misc/dist/osx_template.app/Contents/Info.plist
index a087550290..43399ec6ce 100644
--- a/misc/dist/osx_template.app/Contents/Info.plist
+++ b/misc/dist/osx_template.app/Contents/Info.plist
@@ -8,6 +8,8 @@
<string>$binary</string>
<key>CFBundleName</key>
<string>$name</string>
+ <key>CFBundleDisplayName</key>
+ <string>$name</string>
<key>CFBundleGetInfoString</key>
<string>$info</string>
<key>CFBundleIconFile</key>
diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp
index 58a788e255..8bf5fd1eda 100644
--- a/modules/gdscript/gdscript.cpp
+++ b/modules/gdscript/gdscript.cpp
@@ -796,7 +796,7 @@ void GDScript::_set_subclass_path(Ref<GDScript> &p_sc, const String &p_path) {
String GDScript::_get_debug_path() const {
if (is_built_in() && !get_name().is_empty()) {
- return get_name() + " (" + get_path().get_slice("::", 0) + ")";
+ return get_name() + " (" + get_path() + ")";
} else {
return get_path();
}
diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp
index 2c42879bd3..c70081a620 100644
--- a/modules/gltf/gltf_document.cpp
+++ b/modules/gltf/gltf_document.cpp
@@ -6470,8 +6470,8 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> state, AnimationPlayer *ap,
gltf_animation->get_tracks().insert(transform_track_i.key, track);
}
}
- } else if (String(orig_track_path).contains(":blend_shapes/")) {
- const Vector<String> node_suffix = String(orig_track_path).split(":blend_shapes/");
+ } else if (String(orig_track_path).contains(":") && animation->track_get_type(track_i) == Animation::TYPE_BLEND_SHAPE) {
+ const Vector<String> node_suffix = String(orig_track_path).split(":");
const NodePath path = node_suffix[0];
const String suffix = node_suffix[1];
Node *node = ap->get_parent()->get_node_or_null(path);
diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp
index 07128770b7..272283432d 100644
--- a/modules/mono/editor/bindings_generator.cpp
+++ b/modules/mono/editor/bindings_generator.cpp
@@ -278,12 +278,12 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf
} else if (code_tag) {
xml_output.append("[");
pos = brk_pos + 1;
- } else if (tag.begins_with("method ") || tag.begins_with("member ") || tag.begins_with("signal ") || tag.begins_with("enum ") || tag.begins_with("constant ")) {
+ } else if (tag.begins_with("method ") || tag.begins_with("member ") || tag.begins_with("signal ") || tag.begins_with("enum ") || tag.begins_with("constant ") || tag.begins_with("theme_item ")) {
const int tag_end = tag.find(" ");
const String link_tag = tag.substr(0, tag_end);
const String link_target = tag.substr(tag_end + 1, tag.length()).lstrip(" ");
- Vector<String> link_target_parts = link_target.split(".");
+ const Vector<String> link_target_parts = link_target.split(".");
if (link_target_parts.size() <= 0 || link_target_parts.size() > 2) {
ERR_PRINT("Invalid reference format: '" + tag + "'.");
@@ -311,201 +311,18 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf
}
if (link_tag == "method") {
- if (!target_itype || !target_itype->is_object_type) {
- if (OS::get_singleton()->is_stdout_verbose()) {
- if (target_itype) {
- OS::get_singleton()->print("Cannot resolve method reference for non-Godot.Object type in documentation: %s\n", link_target.utf8().get_data());
- } else {
- OS::get_singleton()->print("Cannot resolve type from method reference in documentation: %s\n", link_target.utf8().get_data());
- }
- }
-
- // TODO Map what we can
- xml_output.append("<c>");
- xml_output.append(link_target);
- xml_output.append("</c>");
- } else {
- const MethodInterface *target_imethod = target_itype->find_method_by_name(target_cname);
-
- if (target_imethod) {
- xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".");
- xml_output.append(target_itype->proxy_name);
- xml_output.append(".");
- xml_output.append(target_imethod->proxy_name);
- xml_output.append("\"/>");
- }
- }
+ _append_xml_method(xml_output, target_itype, target_cname, link_target, link_target_parts);
} else if (link_tag == "member") {
- if (!target_itype || !target_itype->is_object_type) {
- if (OS::get_singleton()->is_stdout_verbose()) {
- if (target_itype) {
- OS::get_singleton()->print("Cannot resolve member reference for non-Godot.Object type in documentation: %s\n", link_target.utf8().get_data());
- } else {
- OS::get_singleton()->print("Cannot resolve type from member reference in documentation: %s\n", link_target.utf8().get_data());
- }
- }
-
- // TODO Map what we can
- xml_output.append("<c>");
- xml_output.append(link_target);
- xml_output.append("</c>");
- } else {
- const PropertyInterface *target_iprop = target_itype->find_property_by_name(target_cname);
-
- if (target_iprop) {
- xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".");
- xml_output.append(target_itype->proxy_name);
- xml_output.append(".");
- xml_output.append(target_iprop->proxy_name);
- xml_output.append("\"/>");
- }
- }
+ _append_xml_member(xml_output, target_itype, target_cname, link_target, link_target_parts);
} else if (link_tag == "signal") {
- if (!target_itype || !target_itype->is_object_type) {
- if (OS::get_singleton()->is_stdout_verbose()) {
- if (target_itype) {
- OS::get_singleton()->print("Cannot resolve signal reference for non-Godot.Object type in documentation: %s\n", link_target.utf8().get_data());
- } else {
- OS::get_singleton()->print("Cannot resolve type from signal reference in documentation: %s\n", link_target.utf8().get_data());
- }
- }
-
- // TODO Map what we can
- xml_output.append("<c>");
- xml_output.append(link_target);
- xml_output.append("</c>");
- } else {
- const SignalInterface *target_isignal = target_itype->find_signal_by_name(target_cname);
-
- if (target_isignal) {
- xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".");
- xml_output.append(target_itype->proxy_name);
- xml_output.append(".");
- xml_output.append(target_isignal->proxy_name);
- xml_output.append("\"/>");
- } else {
- ERR_PRINT("Cannot resolve signal reference in documentation: '" + link_target + "'.");
-
- xml_output.append("<c>");
- xml_output.append(link_target);
- xml_output.append("</c>");
- }
- }
+ _append_xml_signal(xml_output, target_itype, target_cname, link_target, link_target_parts);
} else if (link_tag == "enum") {
- const StringName search_cname = !target_itype ? target_cname : StringName(target_itype->name + "." + (String)target_cname);
-
- const Map<StringName, TypeInterface>::Element *enum_match = enum_types.find(search_cname);
-
- if (!enum_match && search_cname != target_cname) {
- enum_match = enum_types.find(target_cname);
- }
-
- if (enum_match) {
- const TypeInterface &target_enum_itype = enum_match->value();
-
- xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".");
- xml_output.append(target_enum_itype.proxy_name); // Includes nesting class if any
- xml_output.append("\"/>");
- } else {
- ERR_PRINT("Cannot resolve enum reference in documentation: '" + link_target + "'.");
-
- xml_output.append("<c>");
- xml_output.append(link_target);
- xml_output.append("</c>");
- }
+ _append_xml_enum(xml_output, target_itype, target_cname, link_target, link_target_parts);
} else if (link_tag == "constant") {
- if (!target_itype || !target_itype->is_object_type) {
- if (OS::get_singleton()->is_stdout_verbose()) {
- if (target_itype) {
- OS::get_singleton()->print("Cannot resolve constant reference for non-Godot.Object type in documentation: %s\n", link_target.utf8().get_data());
- } else {
- OS::get_singleton()->print("Cannot resolve type from constant reference in documentation: %s\n", link_target.utf8().get_data());
- }
- }
-
- // TODO Map what we can
- xml_output.append("<c>");
- xml_output.append(link_target);
- xml_output.append("</c>");
- } else if (!target_itype && target_cname == name_cache.type_at_GlobalScope) {
- const String target_name = (String)target_cname;
-
- // Try to find as a global constant
- const ConstantInterface *target_iconst = find_constant_by_name(target_name, global_constants);
-
- if (target_iconst) {
- // Found global constant
- xml_output.append("<see cref=\"" BINDINGS_NAMESPACE "." BINDINGS_GLOBAL_SCOPE_CLASS ".");
- xml_output.append(target_iconst->proxy_name);
- xml_output.append("\"/>");
- } else {
- // Try to find as global enum constant
- const EnumInterface *target_ienum = nullptr;
-
- for (const EnumInterface &ienum : global_enums) {
- target_ienum = &ienum;
- target_iconst = find_constant_by_name(target_name, target_ienum->constants);
- if (target_iconst) {
- break;
- }
- }
-
- if (target_iconst) {
- xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".");
- xml_output.append(target_ienum->cname);
- xml_output.append(".");
- xml_output.append(target_iconst->proxy_name);
- xml_output.append("\"/>");
- } else {
- ERR_PRINT("Cannot resolve global constant reference in documentation: '" + link_target + "'.");
-
- xml_output.append("<c>");
- xml_output.append(link_target);
- xml_output.append("</c>");
- }
- }
- } else {
- const String target_name = (String)target_cname;
-
- // Try to find the constant in the current class
- const ConstantInterface *target_iconst = find_constant_by_name(target_name, target_itype->constants);
-
- if (target_iconst) {
- // Found constant in current class
- xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".");
- xml_output.append(target_itype->proxy_name);
- xml_output.append(".");
- xml_output.append(target_iconst->proxy_name);
- xml_output.append("\"/>");
- } else {
- // Try to find as enum constant in the current class
- const EnumInterface *target_ienum = nullptr;
-
- for (const EnumInterface &ienum : target_itype->enums) {
- target_ienum = &ienum;
- target_iconst = find_constant_by_name(target_name, target_ienum->constants);
- if (target_iconst) {
- break;
- }
- }
-
- if (target_iconst) {
- xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".");
- xml_output.append(target_itype->proxy_name);
- xml_output.append(".");
- xml_output.append(target_ienum->cname);
- xml_output.append(".");
- xml_output.append(target_iconst->proxy_name);
- xml_output.append("\"/>");
- } else {
- ERR_PRINT("Cannot resolve constant reference in documentation: '" + link_target + "'.");
-
- xml_output.append("<c>");
- xml_output.append(link_target);
- xml_output.append("</c>");
- }
- }
- }
+ _append_xml_constant(xml_output, target_itype, target_cname, link_target, link_target_parts);
+ } else if (link_tag == "theme_item") {
+ // We do not declare theme_items in any way in C#, so there is nothing to reference
+ _append_xml_undeclared(xml_output, link_target);
}
pos = brk_end + 1;
@@ -670,6 +487,240 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf
return xml_output.as_string();
}
+void BindingsGenerator::_append_xml_method(StringBuilder &p_xml_output, const TypeInterface *p_target_itype, const StringName &p_target_cname, const String &p_link_target, const Vector<String> &p_link_target_parts) {
+ if (p_link_target_parts[0] == name_cache.type_at_GlobalScope) {
+ if (OS::get_singleton()->is_stdout_verbose()) {
+ OS::get_singleton()->print("Cannot resolve @GlobalScope method reference in documentation: %s\n", p_link_target.utf8().get_data());
+ }
+
+ // TODO Map what we can
+ _append_xml_undeclared(p_xml_output, p_link_target);
+ } else if (!p_target_itype || !p_target_itype->is_object_type) {
+ if (OS::get_singleton()->is_stdout_verbose()) {
+ if (p_target_itype) {
+ OS::get_singleton()->print("Cannot resolve method reference for non-Godot.Object type in documentation: %s\n", p_link_target.utf8().get_data());
+ } else {
+ OS::get_singleton()->print("Cannot resolve type from method reference in documentation: %s\n", p_link_target.utf8().get_data());
+ }
+ }
+
+ // TODO Map what we can
+ _append_xml_undeclared(p_xml_output, p_link_target);
+ } else {
+ if (p_target_cname == "_init") {
+ // The _init method is not declared in C#, reference the constructor instead
+ p_xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".");
+ p_xml_output.append(p_target_itype->proxy_name);
+ p_xml_output.append(".");
+ p_xml_output.append(p_target_itype->proxy_name);
+ p_xml_output.append("()\"/>");
+ } else {
+ const MethodInterface *target_imethod = p_target_itype->find_method_by_name(p_target_cname);
+
+ if (target_imethod) {
+ p_xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".");
+ p_xml_output.append(p_target_itype->proxy_name);
+ p_xml_output.append(".");
+ p_xml_output.append(target_imethod->proxy_name);
+ p_xml_output.append("\"/>");
+ } else {
+ ERR_PRINT("Cannot resolve method reference in documentation: '" + p_link_target + "'.");
+ _append_xml_undeclared(p_xml_output, p_link_target);
+ }
+ }
+ }
+}
+
+void BindingsGenerator::_append_xml_member(StringBuilder &p_xml_output, const TypeInterface *p_target_itype, const StringName &p_target_cname, const String &p_link_target, const Vector<String> &p_link_target_parts) {
+ if (p_link_target.find("/") >= 0) {
+ // Properties with '/' (slash) in the name are not declared in C#, so there is nothing to reference.
+ _append_xml_undeclared(p_xml_output, p_link_target);
+ } else if (!p_target_itype || !p_target_itype->is_object_type) {
+ if (OS::get_singleton()->is_stdout_verbose()) {
+ if (p_target_itype) {
+ OS::get_singleton()->print("Cannot resolve member reference for non-Godot.Object type in documentation: %s\n", p_link_target.utf8().get_data());
+ } else {
+ OS::get_singleton()->print("Cannot resolve type from member reference in documentation: %s\n", p_link_target.utf8().get_data());
+ }
+ }
+
+ // TODO Map what we can
+ _append_xml_undeclared(p_xml_output, p_link_target);
+ } else {
+ const TypeInterface *current_itype = p_target_itype;
+ const PropertyInterface *target_iprop = nullptr;
+
+ while (target_iprop == nullptr && current_itype != nullptr) {
+ target_iprop = current_itype->find_property_by_name(p_target_cname);
+ if (target_iprop == nullptr) {
+ current_itype = _get_type_or_null(TypeReference(current_itype->base_name));
+ }
+ }
+
+ if (target_iprop) {
+ p_xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".");
+ p_xml_output.append(current_itype->proxy_name);
+ p_xml_output.append(".");
+ p_xml_output.append(target_iprop->proxy_name);
+ p_xml_output.append("\"/>");
+ } else {
+ ERR_PRINT("Cannot resolve member reference in documentation: '" + p_link_target + "'.");
+ _append_xml_undeclared(p_xml_output, p_link_target);
+ }
+ }
+}
+
+void BindingsGenerator::_append_xml_signal(StringBuilder &p_xml_output, const TypeInterface *p_target_itype, const StringName &p_target_cname, const String &p_link_target, const Vector<String> &p_link_target_parts) {
+ if (!p_target_itype || !p_target_itype->is_object_type) {
+ if (OS::get_singleton()->is_stdout_verbose()) {
+ if (p_target_itype) {
+ OS::get_singleton()->print("Cannot resolve signal reference for non-Godot.Object type in documentation: %s\n", p_link_target.utf8().get_data());
+ } else {
+ OS::get_singleton()->print("Cannot resolve type from signal reference in documentation: %s\n", p_link_target.utf8().get_data());
+ }
+ }
+
+ // TODO Map what we can
+ _append_xml_undeclared(p_xml_output, p_link_target);
+ } else {
+ const SignalInterface *target_isignal = p_target_itype->find_signal_by_name(p_target_cname);
+
+ if (target_isignal) {
+ p_xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".");
+ p_xml_output.append(p_target_itype->proxy_name);
+ p_xml_output.append(".");
+ p_xml_output.append(target_isignal->proxy_name);
+ p_xml_output.append("\"/>");
+ } else {
+ ERR_PRINT("Cannot resolve signal reference in documentation: '" + p_link_target + "'.");
+ _append_xml_undeclared(p_xml_output, p_link_target);
+ }
+ }
+}
+
+void BindingsGenerator::_append_xml_enum(StringBuilder &p_xml_output, const TypeInterface *p_target_itype, const StringName &p_target_cname, const String &p_link_target, const Vector<String> &p_link_target_parts) {
+ const StringName search_cname = !p_target_itype ? p_target_cname : StringName(p_target_itype->name + "." + (String)p_target_cname);
+
+ const Map<StringName, TypeInterface>::Element *enum_match = enum_types.find(search_cname);
+
+ if (!enum_match && search_cname != p_target_cname) {
+ enum_match = enum_types.find(p_target_cname);
+ }
+
+ if (enum_match) {
+ const TypeInterface &target_enum_itype = enum_match->value();
+
+ p_xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".");
+ p_xml_output.append(target_enum_itype.proxy_name); // Includes nesting class if any
+ p_xml_output.append("\"/>");
+ } else {
+ ERR_PRINT("Cannot resolve enum reference in documentation: '" + p_link_target + "'.");
+ _append_xml_undeclared(p_xml_output, p_link_target);
+ }
+}
+
+void BindingsGenerator::_append_xml_constant(StringBuilder &p_xml_output, const TypeInterface *p_target_itype, const StringName &p_target_cname, const String &p_link_target, const Vector<String> &p_link_target_parts) {
+ if (p_link_target_parts[0] == name_cache.type_at_GlobalScope) {
+ _append_xml_constant_in_global_scope(p_xml_output, p_target_cname, p_link_target);
+ } else if (!p_target_itype || !p_target_itype->is_object_type) {
+ // Search in @GlobalScope as a last resort if no class was specified
+ if (p_link_target_parts.size() == 1) {
+ _append_xml_constant_in_global_scope(p_xml_output, p_target_cname, p_link_target);
+ return;
+ }
+
+ if (OS::get_singleton()->is_stdout_verbose()) {
+ if (p_target_itype) {
+ OS::get_singleton()->print("Cannot resolve constant reference for non-Godot.Object type in documentation: %s\n", p_link_target.utf8().get_data());
+ } else {
+ OS::get_singleton()->print("Cannot resolve type from constant reference in documentation: %s\n", p_link_target.utf8().get_data());
+ }
+ }
+
+ // TODO Map what we can
+ _append_xml_undeclared(p_xml_output, p_link_target);
+ } else {
+ // Try to find the constant in the current class
+ const ConstantInterface *target_iconst = find_constant_by_name(p_target_cname, p_target_itype->constants);
+
+ if (target_iconst) {
+ // Found constant in current class
+ p_xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".");
+ p_xml_output.append(p_target_itype->proxy_name);
+ p_xml_output.append(".");
+ p_xml_output.append(target_iconst->proxy_name);
+ p_xml_output.append("\"/>");
+ } else {
+ // Try to find as enum constant in the current class
+ const EnumInterface *target_ienum = nullptr;
+
+ for (const EnumInterface &ienum : p_target_itype->enums) {
+ target_ienum = &ienum;
+ target_iconst = find_constant_by_name(p_target_cname, target_ienum->constants);
+ if (target_iconst) {
+ break;
+ }
+ }
+
+ if (target_iconst) {
+ p_xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".");
+ p_xml_output.append(p_target_itype->proxy_name);
+ p_xml_output.append(".");
+ p_xml_output.append(target_ienum->cname);
+ p_xml_output.append(".");
+ p_xml_output.append(target_iconst->proxy_name);
+ p_xml_output.append("\"/>");
+ } else if (p_link_target_parts.size() == 1) {
+ // Also search in @GlobalScope as a last resort if no class was specified
+ _append_xml_constant_in_global_scope(p_xml_output, p_target_cname, p_link_target);
+ } else {
+ ERR_PRINT("Cannot resolve constant reference in documentation: '" + p_link_target + "'.");
+ _append_xml_undeclared(p_xml_output, p_link_target);
+ }
+ }
+ }
+}
+
+void BindingsGenerator::_append_xml_constant_in_global_scope(StringBuilder &p_xml_output, const String &p_target_cname, const String &p_link_target) {
+ // Try to find as a global constant
+ const ConstantInterface *target_iconst = find_constant_by_name(p_target_cname, global_constants);
+
+ if (target_iconst) {
+ // Found global constant
+ p_xml_output.append("<see cref=\"" BINDINGS_NAMESPACE "." BINDINGS_GLOBAL_SCOPE_CLASS ".");
+ p_xml_output.append(target_iconst->proxy_name);
+ p_xml_output.append("\"/>");
+ } else {
+ // Try to find as global enum constant
+ const EnumInterface *target_ienum = nullptr;
+
+ for (const EnumInterface &ienum : global_enums) {
+ target_ienum = &ienum;
+ target_iconst = find_constant_by_name(p_target_cname, target_ienum->constants);
+ if (target_iconst) {
+ break;
+ }
+ }
+
+ if (target_iconst) {
+ p_xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".");
+ p_xml_output.append(target_ienum->cname);
+ p_xml_output.append(".");
+ p_xml_output.append(target_iconst->proxy_name);
+ p_xml_output.append("\"/>");
+ } else {
+ ERR_PRINT("Cannot resolve global constant reference in documentation: '" + p_link_target + "'.");
+ _append_xml_undeclared(p_xml_output, p_link_target);
+ }
+ }
+}
+
+void BindingsGenerator::_append_xml_undeclared(StringBuilder &p_xml_output, const String &p_link_target) {
+ p_xml_output.append("<c>");
+ p_xml_output.append(p_link_target);
+ p_xml_output.append("</c>");
+}
+
int BindingsGenerator::_determine_enum_prefix(const EnumInterface &p_ienum) {
CRASH_COND(p_ienum.constants.is_empty());
diff --git a/modules/mono/editor/bindings_generator.h b/modules/mono/editor/bindings_generator.h
index 5460f018f0..f601ffde2b 100644
--- a/modules/mono/editor/bindings_generator.h
+++ b/modules/mono/editor/bindings_generator.h
@@ -658,6 +658,14 @@ class BindingsGenerator {
String bbcode_to_xml(const String &p_bbcode, const TypeInterface *p_itype);
+ void _append_xml_method(StringBuilder &p_xml_output, const TypeInterface *p_target_itype, const StringName &p_target_cname, const String &p_link_target, const Vector<String> &p_link_target_parts);
+ void _append_xml_member(StringBuilder &p_xml_output, const TypeInterface *p_target_itype, const StringName &p_target_cname, const String &p_link_target, const Vector<String> &p_link_target_parts);
+ void _append_xml_signal(StringBuilder &p_xml_output, const TypeInterface *p_target_itype, const StringName &p_target_cname, const String &p_link_target, const Vector<String> &p_link_target_parts);
+ void _append_xml_enum(StringBuilder &p_xml_output, const TypeInterface *p_target_itype, const StringName &p_target_cname, const String &p_link_target, const Vector<String> &p_link_target_parts);
+ void _append_xml_constant(StringBuilder &p_xml_output, const TypeInterface *p_target_itype, const StringName &p_target_cname, const String &p_link_target, const Vector<String> &p_link_target_parts);
+ void _append_xml_constant_in_global_scope(StringBuilder &p_xml_output, const String &p_target_cname, const String &p_link_target);
+ void _append_xml_undeclared(StringBuilder &p_xml_output, const String &p_link_target);
+
int _determine_enum_prefix(const EnumInterface &p_ienum);
void _apply_prefix_to_enum_constants(EnumInterface &p_ienum, int p_prefix_length);
diff --git a/platform/iphone/export/export_plugin.cpp b/platform/iphone/export/export_plugin.cpp
index 69c6df8a38..2eaf5e47ac 100644
--- a/platform/iphone/export/export_plugin.cpp
+++ b/platform/iphone/export/export_plugin.cpp
@@ -389,6 +389,36 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_
String value = value_format.format(value_dictionary, "$_");
strnew += lines[i].replace("$launch_screen_background_color", value) + "\n";
+ } else if (lines[i].find("$pbx_locale_file_reference") != -1) {
+ String locale_files;
+ Vector<String> translations = ProjectSettings::get_singleton()->get("internationalization/locale/translations");
+ if (translations.size() > 0) {
+ int index = 0;
+ for (const String &E : translations) {
+ Ref<Translation> tr = ResourceLoader::load(E);
+ if (tr.is_valid()) {
+ String lang = tr->get_locale();
+ locale_files += "D0BCFE4518AEBDA2004A" + itos(index).pad_zeros(4) + " /* " + lang + " */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = " + lang + "; path = " + lang + ".lproj/InfoPlist.strings; sourceTree = \"<group>\"; };";
+ }
+ index++;
+ }
+ }
+ strnew += lines[i].replace("$pbx_locale_file_reference", locale_files);
+ } else if (lines[i].find("$pbx_locale_build_reference") != -1) {
+ String locale_files;
+ Vector<String> translations = ProjectSettings::get_singleton()->get("internationalization/locale/translations");
+ if (translations.size() > 0) {
+ int index = 0;
+ for (const String &E : translations) {
+ Ref<Translation> tr = ResourceLoader::load(E);
+ if (tr.is_valid()) {
+ String lang = tr->get_locale();
+ locale_files += "D0BCFE4518AEBDA2004A" + itos(index).pad_zeros(4) + " /* " + lang + " */,";
+ }
+ index++;
+ }
+ }
+ strnew += lines[i].replace("$pbx_locale_build_reference", locale_files);
} else {
strnew += lines[i] + "\n";
}
@@ -1593,6 +1623,29 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
return ERR_FILE_NOT_FOUND;
}
+ Vector<String> translations = ProjectSettings::get_singleton()->get("internationalization/locale/translations");
+ if (translations.size() > 0) {
+ {
+ String fname = dest_dir + binary_name + "/en.lproj";
+ tmp_app_path->make_dir_recursive(fname);
+ FileAccessRef f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE);
+ f->store_line("CFBundleDisplayName = \"" + ProjectSettings::get_singleton()->get("application/config/name").operator String() + "\";");
+ }
+
+ for (const String &E : translations) {
+ Ref<Translation> tr = ResourceLoader::load(E);
+ if (tr.is_valid()) {
+ String fname = dest_dir + binary_name + "/" + tr->get_locale() + ".lproj";
+ tmp_app_path->make_dir_recursive(fname);
+ FileAccessRef f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE);
+ String prop = "application/config/name_" + tr->get_locale();
+ if (ProjectSettings::get_singleton()->has_setting(prop)) {
+ f->store_line("CFBundleDisplayName = \"" + ProjectSettings::get_singleton()->get(prop).operator String() + "\";");
+ }
+ }
+ }
+ }
+
// Copy project static libs to the project
Vector<Ref<EditorExportPlugin>> export_plugins = EditorExport::get_singleton()->get_export_plugins();
for (int i = 0; i < export_plugins.size(); i++) {
diff --git a/platform/linuxbsd/display_server_x11.cpp b/platform/linuxbsd/display_server_x11.cpp
index bf3bfe9553..1ed4d8fb32 100644
--- a/platform/linuxbsd/display_server_x11.cpp
+++ b/platform/linuxbsd/display_server_x11.cpp
@@ -109,6 +109,15 @@ struct Hints {
unsigned long status = 0;
};
+static String get_atom_name(Display *p_disp, Atom p_atom) {
+ char *name = XGetAtomName(p_disp, p_atom);
+ ERR_FAIL_NULL_V_MSG(name, String(), "Atom is invalid.");
+ String ret;
+ ret.parse_utf8(name);
+ XFree(name);
+ return ret;
+}
+
bool DisplayServerX11::has_feature(Feature p_feature) const {
switch (p_feature) {
case FEATURE_SUBWINDOWS:
@@ -435,7 +444,7 @@ String DisplayServerX11::_clipboard_get_impl(Atom p_source, Window x11_window, A
Window selection_owner = XGetSelectionOwner(x11_display, p_source);
if (selection_owner == x11_window) {
static const char *target_type = "PRIMARY";
- if (p_source != None && String(XGetAtomName(x11_display, p_source)) == target_type) {
+ if (p_source != None && get_atom_name(x11_display, p_source) == target_type) {
return internal_clipboard_primary;
} else {
return internal_clipboard;
@@ -2448,8 +2457,7 @@ String DisplayServerX11::keyboard_get_layout_language(int p_index) const {
Atom names = kbd->names->symbols;
if (names != None) {
- char *name = XGetAtomName(x11_display, names);
- Vector<String> info = String(name).split("+");
+ Vector<String> info = get_atom_name(x11_display, names).split("+");
if (p_index >= 0 && p_index < _group_count) {
if (p_index + 1 < info.size()) {
ret = info[p_index + 1]; // Skip "pc" at the start and "inet"/"group" at the end of symbols.
@@ -2459,7 +2467,6 @@ String DisplayServerX11::keyboard_get_layout_language(int p_index) const {
} else {
ERR_PRINT("Index " + itos(p_index) + "is out of bounds (" + itos(_group_count) + ").");
}
- XFree(name);
}
XkbFreeKeyboard(kbd, 0, true);
}
@@ -2486,9 +2493,7 @@ String DisplayServerX11::keyboard_get_layout_name(int p_index) const {
}
if (p_index >= 0 && p_index < _group_count) {
- char *full_name = XGetAtomName(x11_display, groups[p_index]);
- ret.parse_utf8(full_name);
- XFree(full_name);
+ ret = get_atom_name(x11_display, groups[p_index]);
} else {
ERR_PRINT("Index " + itos(p_index) + "is out of bounds (" + itos(_group_count) + ").");
}
@@ -2551,7 +2556,7 @@ static Atom pick_target_from_list(Display *p_display, Atom *p_list, int p_count)
for (int i = 0; i < p_count; i++) {
Atom atom = p_list[i];
- if (atom != None && String(XGetAtomName(p_display, atom)) == target_type) {
+ if (atom != None && get_atom_name(p_display, atom) == target_type) {
return atom;
}
}
@@ -2560,15 +2565,15 @@ static Atom pick_target_from_list(Display *p_display, Atom *p_list, int p_count)
static Atom pick_target_from_atoms(Display *p_disp, Atom p_t1, Atom p_t2, Atom p_t3) {
static const char *target_type = "text/uri-list";
- if (p_t1 != None && String(XGetAtomName(p_disp, p_t1)) == target_type) {
+ if (p_t1 != None && get_atom_name(p_disp, p_t1) == target_type) {
return p_t1;
}
- if (p_t2 != None && String(XGetAtomName(p_disp, p_t2)) == target_type) {
+ if (p_t2 != None && get_atom_name(p_disp, p_t2) == target_type) {
return p_t2;
}
- if (p_t3 != None && String(XGetAtomName(p_disp, p_t3)) == target_type) {
+ if (p_t3 != None && get_atom_name(p_disp, p_t3) == target_type) {
return p_t3;
}
@@ -2890,7 +2895,7 @@ Atom DisplayServerX11::_process_selection_request_target(Atom p_target, Window p
// is the owner during a selection request.
CharString clip;
static const char *target_type = "PRIMARY";
- if (p_selection != None && String(XGetAtomName(x11_display, p_selection)) == target_type) {
+ if (p_selection != None && get_atom_name(x11_display, p_selection) == target_type) {
clip = internal_clipboard_primary.utf8();
} else {
clip = internal_clipboard.utf8();
@@ -3914,6 +3919,7 @@ void DisplayServerX11::process_events() {
Property p = _read_property(x11_display, windows[window_id].x11_window, XInternAtom(x11_display, "PRIMARY", 0));
Vector<String> files = String((char *)p.data).split("\n", false);
+ XFree(p.data);
for (int i = 0; i < files.size(); i++) {
files.write[i] = files[i].replace("file://", "").uri_decode().strip_edges();
}
@@ -3956,6 +3962,7 @@ void DisplayServerX11::process_events() {
if (more_than_3) {
Property p = _read_property(x11_display, source, XInternAtom(x11_display, "XdndTypeList", False));
requested = pick_target_from_list(x11_display, (Atom *)p.data, p.nitems);
+ XFree(p.data);
} else {
requested = pick_target_from_atoms(x11_display, event.xclient.data.l[2], event.xclient.data.l[3], event.xclient.data.l[4]);
}
diff --git a/platform/osx/display_server_osx.h b/platform/osx/display_server_osx.h
index 036e74c47c..cc9ac162ea 100644
--- a/platform/osx/display_server_osx.h
+++ b/platform/osx/display_server_osx.h
@@ -160,6 +160,7 @@ private:
float display_max_scale = 1.f;
Point2i origin;
bool displays_arrangement_dirty = true;
+ bool is_resizing = false;
CursorShape cursor_shape = CURSOR_ARROW;
NSCursor *cursors[CURSOR_MAX];
@@ -206,6 +207,8 @@ public:
void mouse_process_popups(bool p_close = false);
void popup_open(WindowID p_window);
void popup_close(WindowID p_window);
+ void set_is_resizing(bool p_is_resizing);
+ bool get_is_resizing() const;
void window_update(WindowID p_window);
void window_destroy(WindowID p_window);
diff --git a/platform/osx/display_server_osx.mm b/platform/osx/display_server_osx.mm
index 23f37a8e18..a4cd8f58bd 100644
--- a/platform/osx/display_server_osx.mm
+++ b/platform/osx/display_server_osx.mm
@@ -599,6 +599,14 @@ void DisplayServerOSX::set_last_focused_window(WindowID p_window) {
last_focused_window = p_window;
}
+void DisplayServerOSX::set_is_resizing(bool p_is_resizing) {
+ is_resizing = p_is_resizing;
+}
+
+bool DisplayServerOSX::get_is_resizing() const {
+ return is_resizing;
+}
+
void DisplayServerOSX::window_update(WindowID p_window) {
#if defined(GLES3_ENABLED)
if (gl_manager) {
diff --git a/platform/osx/export/export_plugin.cpp b/platform/osx/export/export_plugin.cpp
index 24b9bc02a2..4d0fc9add6 100644
--- a/platform/osx/export/export_plugin.cpp
+++ b/platform/osx/export/export_plugin.cpp
@@ -787,6 +787,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
String fname = tmp_app_path_name + "/Contents/Resources/en.lproj";
tmp_app_dir->make_dir_recursive(fname);
FileAccessRef f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE);
+ f->store_line("CFBundleDisplayName = \"" + ProjectSettings::get_singleton()->get("application/config/name").operator String() + "\";");
}
for (const String &E : translations) {
@@ -795,6 +796,10 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
String fname = tmp_app_path_name + "/Contents/Resources/" + tr->get_locale() + ".lproj";
tmp_app_dir->make_dir_recursive(fname);
FileAccessRef f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE);
+ String prop = "application/config/name_" + tr->get_locale();
+ if (ProjectSettings::get_singleton()->has_setting(prop)) {
+ f->store_line("CFBundleDisplayName = \"" + ProjectSettings::get_singleton()->get(prop).operator String() + "\";");
+ }
}
}
}
diff --git a/platform/osx/godot_window_delegate.mm b/platform/osx/godot_window_delegate.mm
index dbc244650e..9f49a6a4e9 100644
--- a/platform/osx/godot_window_delegate.mm
+++ b/platform/osx/godot_window_delegate.mm
@@ -149,6 +149,20 @@
}
}
+- (void)windowWillStartLiveResize:(NSNotification *)notification {
+ DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton();
+ if (ds) {
+ ds->set_is_resizing(true);
+ }
+}
+
+- (void)windowDidEndLiveResize:(NSNotification *)notification {
+ DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton();
+ if (ds) {
+ ds->set_is_resizing(false);
+ }
+}
+
- (void)windowDidResize:(NSNotification *)notification {
DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton();
if (!ds || !ds->has_window(window_id)) {
diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm
index 6700f8fe82..7e0cf9f9cc 100644
--- a/platform/osx/os_osx.mm
+++ b/platform/osx/os_osx.mm
@@ -58,7 +58,8 @@ _FORCE_INLINE_ String OS_OSX::get_framework_executable(const String &p_path) {
void OS_OSX::pre_wait_observer_cb(CFRunLoopObserverRef p_observer, CFRunLoopActivity p_activiy, void *p_context) {
// Prevent main loop from sleeping and redraw window during resize / modal popups.
- if (get_singleton()->get_main_loop()) {
+ DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton();
+ if (get_singleton()->get_main_loop() && ds && (get_singleton()->get_render_thread_mode() != RENDER_SEPARATE_THREAD || !ds->get_is_resizing())) {
Main::force_redraw();
if (!Main::is_iterating()) { // Avoid cyclic loop.
Main::iteration();
diff --git a/scene/gui/button.cpp b/scene/gui/button.cpp
index 27e8b102be..724714b93b 100644
--- a/scene/gui/button.cpp
+++ b/scene/gui/button.cpp
@@ -583,8 +583,8 @@ void Button::_bind_methods() {
Button::Button(const String &p_text) {
text_buf.instantiate();
text_buf->set_flags(TextServer::BREAK_MANDATORY);
-
set_mouse_filter(MOUSE_FILTER_STOP);
+
set_text(p_text);
}
diff --git a/scene/gui/check_button.cpp b/scene/gui/check_button.cpp
index 5e3131f8a0..527b0061ac 100644
--- a/scene/gui/check_button.cpp
+++ b/scene/gui/check_button.cpp
@@ -111,9 +111,12 @@ void CheckButton::_notification(int p_what) {
}
}
-CheckButton::CheckButton() {
+CheckButton::CheckButton(const String &p_text) :
+ Button(p_text) {
set_toggle_mode(true);
+
set_text_alignment(HORIZONTAL_ALIGNMENT_LEFT);
+
if (is_layout_rtl()) {
_set_internal_margin(SIDE_LEFT, get_icon_size().width);
} else {
diff --git a/scene/gui/check_button.h b/scene/gui/check_button.h
index 9a72d04db2..7d4bb8bdfc 100644
--- a/scene/gui/check_button.h
+++ b/scene/gui/check_button.h
@@ -42,7 +42,7 @@ protected:
void _notification(int p_what);
public:
- CheckButton();
+ CheckButton(const String &p_text = String());
~CheckButton();
};
diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp
index 3ea2a9795d..aa4391e9f1 100644
--- a/scene/gui/color_picker.cpp
+++ b/scene/gui/color_picker.cpp
@@ -1429,7 +1429,8 @@ void ColorPickerButton::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "edit_alpha"), "set_edit_alpha", "is_editing_alpha");
}
-ColorPickerButton::ColorPickerButton() {
+ColorPickerButton::ColorPickerButton(const String &p_text) :
+ Button(p_text) {
set_toggle_mode(true);
}
diff --git a/scene/gui/color_picker.h b/scene/gui/color_picker.h
index d6067b1cf4..6f3e16009c 100644
--- a/scene/gui/color_picker.h
+++ b/scene/gui/color_picker.h
@@ -231,7 +231,7 @@ public:
ColorPicker *get_picker();
PopupPanel *get_popup();
- ColorPickerButton();
+ ColorPickerButton(const String &p_text = String());
};
VARIANT_ENUM_CAST(ColorPicker::PickerShapeType);
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index ff4e071a95..6ad296d7c7 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -2437,7 +2437,7 @@ void LineEdit::_ensure_menu() {
}
}
-LineEdit::LineEdit() {
+LineEdit::LineEdit(const String &p_placeholder) {
text_rid = TS->create_shaped_text();
_create_undo_state();
@@ -2452,6 +2452,8 @@ LineEdit::LineEdit() {
caret_blink_timer->connect("timeout", callable_mp(this, &LineEdit::_toggle_draw_caret));
set_caret_blink_enabled(false);
+ set_placeholder(p_placeholder);
+
set_editable(true); // Initialise to opposite first, so we get past the early-out in set_editable.
}
diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h
index 1519c09d73..444c9a1c50 100644
--- a/scene/gui/line_edit.h
+++ b/scene/gui/line_edit.h
@@ -332,7 +332,7 @@ public:
void show_virtual_keyboard();
- LineEdit();
+ LineEdit(const String &p_placeholder = String());
~LineEdit();
};
diff --git a/scene/gui/link_button.cpp b/scene/gui/link_button.cpp
index 8f40f717c2..dc4f09d22d 100644
--- a/scene/gui/link_button.cpp
+++ b/scene/gui/link_button.cpp
@@ -317,8 +317,10 @@ void LinkButton::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "structured_text_bidi_override_options"), "set_structured_text_bidi_override_options", "get_structured_text_bidi_override_options");
}
-LinkButton::LinkButton() {
+LinkButton::LinkButton(const String &p_text) {
text_buf.instantiate();
set_focus_mode(FOCUS_NONE);
set_default_cursor_shape(CURSOR_POINTING_HAND);
+
+ set_text(p_text);
}
diff --git a/scene/gui/link_button.h b/scene/gui/link_button.h
index a455e866b1..f996558f32 100644
--- a/scene/gui/link_button.h
+++ b/scene/gui/link_button.h
@@ -90,7 +90,7 @@ public:
void set_underline_mode(UnderlineMode p_underline_mode);
UnderlineMode get_underline_mode() const;
- LinkButton();
+ LinkButton(const String &p_text = String());
};
VARIANT_ENUM_CAST(LinkButton::UnderlineMode);
diff --git a/scene/gui/menu_button.cpp b/scene/gui/menu_button.cpp
index 46d8a61ca1..c04690cdb3 100644
--- a/scene/gui/menu_button.cpp
+++ b/scene/gui/menu_button.cpp
@@ -227,7 +227,8 @@ void MenuButton::set_disable_shortcuts(bool p_disabled) {
disable_shortcuts = p_disabled;
}
-MenuButton::MenuButton() {
+MenuButton::MenuButton(const String &p_text) :
+ Button(p_text) {
set_flat(true);
set_toggle_mode(true);
set_disable_shortcuts(false);
diff --git a/scene/gui/menu_button.h b/scene/gui/menu_button.h
index 3647a69d33..9cfb780255 100644
--- a/scene/gui/menu_button.h
+++ b/scene/gui/menu_button.h
@@ -67,7 +67,7 @@ public:
void set_item_count(int p_count);
int get_item_count() const;
- MenuButton();
+ MenuButton(const String &p_text = String());
~MenuButton();
};
diff --git a/scene/gui/option_button.cpp b/scene/gui/option_button.cpp
index 698d74843c..b3804e73d9 100644
--- a/scene/gui/option_button.cpp
+++ b/scene/gui/option_button.cpp
@@ -412,7 +412,8 @@ void OptionButton::_bind_methods() {
ADD_SIGNAL(MethodInfo("item_focused", PropertyInfo(Variant::INT, "index")));
}
-OptionButton::OptionButton() {
+OptionButton::OptionButton(const String &p_text) :
+ Button(p_text) {
set_toggle_mode(true);
set_text_alignment(HORIZONTAL_ALIGNMENT_LEFT);
if (is_layout_rtl()) {
diff --git a/scene/gui/option_button.h b/scene/gui/option_button.h
index adf2bb90ef..5352fe18a6 100644
--- a/scene/gui/option_button.h
+++ b/scene/gui/option_button.h
@@ -94,7 +94,7 @@ public:
virtual void get_translatable_strings(List<String> *p_strings) const override;
- OptionButton();
+ OptionButton(const String &p_text = String());
~OptionButton();
};
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index dd07831b83..1c9eb14a24 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -4712,7 +4712,7 @@ Dictionary RichTextLabel::parse_expressions_for_values(Vector<String> p_expressi
return d;
}
-RichTextLabel::RichTextLabel() {
+RichTextLabel::RichTextLabel(const String &p_text) {
main = memnew(ItemFrame);
main->index = 0;
current = main;
@@ -4734,6 +4734,8 @@ RichTextLabel::RichTextLabel() {
vscroll->set_step(1);
vscroll->hide();
+ set_text(p_text);
+
set_clip_contents(true);
}
diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h
index 53c2046c8f..076b68a0da 100644
--- a/scene/gui/rich_text_label.h
+++ b/scene/gui/rich_text_label.h
@@ -620,7 +620,7 @@ public:
void set_fixed_size_to_width(int p_width);
virtual Size2 get_minimum_size() const override;
- RichTextLabel();
+ RichTextLabel(const String &p_text = String());
~RichTextLabel();
};
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 854a9e463c..05fda7128c 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -5664,8 +5664,10 @@ void TextEdit::_generate_context_menu() {
if (editable) {
menu->add_item(RTR("Paste"), MENU_PASTE, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_paste") : Key::NONE);
}
- menu->add_separator();
- if (is_selecting_enabled()) {
+ if (selecting_enabled || editable) {
+ menu->add_separator();
+ }
+ if (selecting_enabled) {
menu->add_item(RTR("Select All"), MENU_SELECT_ALL, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_text_select_all") : Key::NONE);
}
if (editable) {
@@ -6579,7 +6581,7 @@ void TextEdit::_base_remove_text(int p_from_line, int p_from_column, int p_to_li
emit_signal(SNAME("lines_edited_from"), p_to_line, p_from_line);
}
-TextEdit::TextEdit() {
+TextEdit::TextEdit(const String &p_placeholder) {
placeholder_data_buf.instantiate();
clear();
@@ -6621,5 +6623,7 @@ TextEdit::TextEdit() {
undo_stack_max_size = GLOBAL_GET("gui/common/text_edit_undo_stack_max_size");
+ set_placeholder(p_placeholder);
+
set_editable(true);
}
diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h
index 83a63ae40a..6deaf76e5e 100644
--- a/scene/gui/text_edit.h
+++ b/scene/gui/text_edit.h
@@ -940,7 +940,7 @@ public:
void set_draw_spaces(bool p_enabled);
bool is_drawing_spaces() const;
- TextEdit();
+ TextEdit(const String &p_placeholder = String());
};
VARIANT_ENUM_CAST(TextEdit::CaretType);