summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/classes/@GlobalScope.xml2
-rw-r--r--doc/classes/Camera.xml18
-rw-r--r--doc/classes/Color.xml2
-rw-r--r--doc/classes/EditorNavigationMeshGenerator.xml31
-rw-r--r--doc/classes/NavigationMesh.xml28
-rw-r--r--doc/classes/OS.xml24
-rw-r--r--doc/classes/ProjectSettings.xml4
-rw-r--r--doc/classes/SceneTree.xml6
-rw-r--r--doc/classes/SpatialMaterial.xml6
-rw-r--r--doc/classes/SurfaceTool.xml18
-rw-r--r--doc/classes/Tree.xml6
-rw-r--r--doc/classes/VehicleWheel.xml6
-rw-r--r--doc/classes/VisualServer.xml2
-rw-r--r--doc/classes/VisualShader.xml22
-rw-r--r--doc/classes/VisualShaderNodeExpression.xml23
-rw-r--r--doc/classes/VisualShaderNodeGroupBase.xml205
-rw-r--r--editor/editor_node.cpp7
-rw-r--r--editor/editor_node.h1
-rw-r--r--editor/editor_plugin.cpp20
-rw-r--r--editor/editor_plugin.h4
-rw-r--r--editor/plugins/sprite_editor_plugin.cpp36
-rw-r--r--editor/plugins/sprite_editor_plugin.h2
-rw-r--r--editor/plugins/tile_map_editor_plugin.cpp53
-rw-r--r--editor/scene_tree_dock.cpp64
-rw-r--r--editor/scene_tree_dock.h5
-rw-r--r--platform/android/java/src/org/godotengine/godot/Godot.java3
-rw-r--r--platform/android/java/src/org/godotengine/godot/GodotView.java72
-rw-r--r--platform/android/java_godot_wrapper.cpp8
-rw-r--r--platform/android/java_godot_wrapper.h2
-rw-r--r--platform/android/os_android.cpp4
-rw-r--r--scene/2d/tile_map.cpp97
-rw-r--r--scene/3d/arvr_nodes.cpp6
-rw-r--r--scene/3d/arvr_nodes.h2
-rw-r--r--scene/3d/camera.cpp10
-rw-r--r--scene/3d/camera.h2
-rw-r--r--scene/main/node.cpp4
36 files changed, 589 insertions, 216 deletions
diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml
index d1e2a9c910..760287e1b8 100644
--- a/doc/classes/@GlobalScope.xml
+++ b/doc/classes/@GlobalScope.xml
@@ -45,6 +45,8 @@
<member name="Marshalls" type="Reference" setter="" getter="">
[Marshalls] singleton
</member>
+ <member name="NavigationMeshGenerator" type="EditorNavigationMeshGenerator" setter="" getter="">
+ </member>
<member name="OS" type="OS" setter="" getter="">
[OS] singleton
</member>
diff --git a/doc/classes/Camera.xml b/doc/classes/Camera.xml
index 0b7021b4a1..cc869d28a2 100644
--- a/doc/classes/Camera.xml
+++ b/doc/classes/Camera.xml
@@ -18,6 +18,13 @@
If this is the current Camera, remove it from being current. If [code]enable_next[/code] is [code]true[/code], request to make the next Camera current, if any.
</description>
</method>
+ <method name="get_camera_rid" qualifiers="const">
+ <return type="RID">
+ </return>
+ <description>
+ Returns the camera's RID from the [VisualServer].
+ </description>
+ </method>
<method name="get_camera_transform" qualifiers="const">
<return type="Transform">
</return>
@@ -39,13 +46,6 @@
<description>
</description>
</method>
- <method name="get_camera_rid" qualifiers="const">
- <return type="RID">
- </return>
- <description>
- Returns the camera's RID from the [VisualServer].
- </description>
- </method>
<method name="is_position_behind" qualifiers="const">
<return type="bool">
</return>
@@ -76,8 +76,10 @@
</return>
<argument index="0" name="screen_point" type="Vector2">
</argument>
+ <argument index="1" name="z_depth" type="float" default="0">
+ </argument>
<description>
- Returns the 3D point in worldspace that maps to the given 2D coordinate in the [Viewport] rectangle.
+ Returns the 3D point in worldspace that maps to the given 2D coordinate in the [Viewport] rectangle on a plane that is the given distance into the scene away from the camera.
</description>
</method>
<method name="project_ray_normal" qualifiers="const">
diff --git a/doc/classes/Color.xml b/doc/classes/Color.xml
index 9f48f6e018..ab5d7a0a5d 100644
--- a/doc/classes/Color.xml
+++ b/doc/classes/Color.xml
@@ -566,6 +566,8 @@
</constant>
<constant name="tomato" value="Color( 1, 0.39, 0.28, 1 )">
</constant>
+ <constant name="transparent" value="Color( 1, 1, 1, 0 )">
+ </constant>
<constant name="turquoise" value="Color( 0.25, 0.88, 0.82, 1 )">
</constant>
<constant name="violet" value="Color( 0.93, 0.51, 0.93, 1 )">
diff --git a/doc/classes/EditorNavigationMeshGenerator.xml b/doc/classes/EditorNavigationMeshGenerator.xml
new file mode 100644
index 0000000000..3956e12509
--- /dev/null
+++ b/doc/classes/EditorNavigationMeshGenerator.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="EditorNavigationMeshGenerator" inherits="Object" category="Core" version="3.2">
+ <brief_description>
+ </brief_description>
+ <description>
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ <method name="bake">
+ <return type="void">
+ </return>
+ <argument index="0" name="nav_mesh" type="NavigationMesh">
+ </argument>
+ <argument index="1" name="root_node" type="Node">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="clear">
+ <return type="void">
+ </return>
+ <argument index="0" name="nav_mesh" type="NavigationMesh">
+ </argument>
+ <description>
+ </description>
+ </method>
+ </methods>
+ <constants>
+ </constants>
+</class>
diff --git a/doc/classes/NavigationMesh.xml b/doc/classes/NavigationMesh.xml
index 2788eb053a..79ad7f63ae 100644
--- a/doc/classes/NavigationMesh.xml
+++ b/doc/classes/NavigationMesh.xml
@@ -29,6 +29,14 @@
<description>
</description>
</method>
+ <method name="get_collision_mask_bit" qualifiers="const">
+ <return type="bool">
+ </return>
+ <argument index="0" name="bit" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="get_polygon">
<return type="PoolIntArray">
</return>
@@ -49,6 +57,16 @@
<description>
</description>
</method>
+ <method name="set_collision_mask_bit">
+ <return type="void">
+ </return>
+ <argument index="0" name="bit" type="int">
+ </argument>
+ <argument index="1" name="value" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="set_vertices">
<return type="void">
</return>
@@ -85,6 +103,10 @@
</member>
<member name="filter/low_hanging_obstacles" type="bool" setter="set_filter_low_hanging_obstacles" getter="get_filter_low_hanging_obstacles">
</member>
+ <member name="geometry/collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask">
+ </member>
+ <member name="geometry/parsed_geometry_type" type="int" setter="set_parsed_geometry_type" getter="get_parsed_geometry_type">
+ </member>
<member name="polygon/verts_per_poly" type="float" setter="set_verts_per_poly" getter="get_verts_per_poly">
</member>
<member name="region/merge_size" type="float" setter="set_region_merge_size" getter="get_region_merge_size">
@@ -101,5 +123,11 @@
</constant>
<constant name="SAMPLE_PARTITION_LAYERS" value="2">
</constant>
+ <constant name="PARSED_GEOMETRY_MESH_INSTANCES" value="0">
+ </constant>
+ <constant name="PARSED_GEOMETRY_STATIC_COLLIDERS" value="1">
+ </constant>
+ <constant name="PARSED_GEOMETRY_BOTH" value="2">
+ </constant>
</constants>
</class>
diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml
index ec2ee78701..dd0fcd63e7 100644
--- a/doc/classes/OS.xml
+++ b/doc/classes/OS.xml
@@ -97,6 +97,8 @@
</argument>
<argument index="3" name="output" type="Array" default="[ ]">
</argument>
+ <argument index="4" name="read_stderr" type="bool" default="false">
+ </argument>
<description>
Execute the file at the given path with the arguments passed as an array of strings. Platform path resolution will take place. The resolved file must exist and be executable.
The arguments are used in the given order and separated by a space, so [code]OS.execute('ping', ['-w', '3', 'godotengine.org'], false)[/code] will resolve to [code]ping -w 3 godotengine.org[/code] in the system's shell.
@@ -701,17 +703,6 @@
The same image is used for window caption, taskbar/dock and window selection dialog. Image is scaled as needed.
</description>
</method>
- <method name="set_native_icon">
- <return type="void">
- </return>
- <argument index="0" name="filename" type="String">
- </argument>
- <description>
- Sets the game's icon using a multi-size platform-specific icon file ([code]*.ico[/code] on Windows and [code]*.icns[/code] on macOS).
- Appropriate size sub-icons are used for window caption, taskbar/dock and window selection dialog.
- Note: This method is only implemented on macOS and Windows.
- </description>
- </method>
<method name="set_ime_active">
<return type="void">
</return>
@@ -730,6 +721,17 @@
Sets position of IME suggestion list popup (in window coordinates).
</description>
</method>
+ <method name="set_native_icon">
+ <return type="void">
+ </return>
+ <argument index="0" name="filename" type="String">
+ </argument>
+ <description>
+ Sets the game's icon using a multi-size platform-specific icon file ([code]*.ico[/code] on Windows and [code]*.icns[/code] on macOS).
+ Appropriate size sub-icons are used for window caption, taskbar/dock and window selection dialog.
+ Note: This method is only implemented on macOS and Windows.
+ </description>
+ </method>
<method name="set_thread_name">
<return type="int" enum="Error">
</return>
diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml
index 4b5500d077..ff8b702859 100644
--- a/doc/classes/ProjectSettings.xml
+++ b/doc/classes/ProjectSettings.xml
@@ -180,6 +180,8 @@
<member name="application/config/icon" type="String" setter="" getter="">
Icon used for the project, set when project loads. Exporters will also use this icon when possible.
</member>
+ <member name="application/config/macos_native_icon" type="String" setter="" getter="">
+ </member>
<member name="application/config/name" type="String" setter="" getter="">
The project's name. It is used both by the Project Manager and by exporters. The project name can be translated by translating its value in localization files.
</member>
@@ -189,6 +191,8 @@
<member name="application/config/use_custom_user_dir" type="bool" setter="" getter="">
If [code]true[/code], the project will save user data to its own user directory (see [member application/config/custom_user_dir_name]). This setting is only effective on desktop platforms. A name must be set in the [member application/config/custom_user_dir_name] setting for this to take effect. If [code]false[/code], the project will save user data to [code](OS user data directory)/Godot/app_userdata/(project name)[/code].
</member>
+ <member name="application/config/windows_native_icon" type="String" setter="" getter="">
+ </member>
<member name="application/run/disable_stderr" type="bool" setter="" getter="">
If [code]true[/code], disables printing to standard error in an exported build.
</member>
diff --git a/doc/classes/SceneTree.xml b/doc/classes/SceneTree.xml
index 0b1f659da3..a236d776c7 100644
--- a/doc/classes/SceneTree.xml
+++ b/doc/classes/SceneTree.xml
@@ -359,6 +359,12 @@
Emitted whenever a node is removed from the SceneTree.
</description>
</signal>
+ <signal name="node_renamed">
+ <argument index="0" name="node" type="Node">
+ </argument>
+ <description>
+ </description>
+ </signal>
<signal name="physics_frame">
<description>
Emitted immediately before [method Node._physics_process] is called on every node in the SceneTree.
diff --git a/doc/classes/SpatialMaterial.xml b/doc/classes/SpatialMaterial.xml
index 8e93160af9..f0df5fac4a 100644
--- a/doc/classes/SpatialMaterial.xml
+++ b/doc/classes/SpatialMaterial.xml
@@ -120,6 +120,8 @@
<member name="flags_use_point_size" type="bool" setter="set_flag" getter="get_flag">
If [code]true[/code], render point size can be changed. Note: this is only effective for objects whose geometry is point-based rather than triangle-based. See also [member params_point_size].
</member>
+ <member name="flags_use_shadow_to_opacity" type="bool" setter="set_flag" getter="get_flag">
+ </member>
<member name="flags_vertex_lighting" type="bool" setter="set_flag" getter="get_flag">
If [code]true[/code], lighting is calculated per vertex rather than per pixel. This may increase performance on low-end devices. Default value: [code]false[/code].
</member>
@@ -390,7 +392,9 @@
</constant>
<constant name="FLAG_ENSURE_CORRECT_NORMALS" value="16" enum="Flags">
</constant>
- <constant name="FLAG_MAX" value="18" enum="Flags">
+ <constant name="FLAG_USE_SHADOW_TO_OPACITY" value="18" enum="Flags">
+ </constant>
+ <constant name="FLAG_MAX" value="19" enum="Flags">
</constant>
<constant name="DIFFUSE_BURLEY" value="0" enum="DiffuseMode">
Default diffuse scattering algorithm.
diff --git a/doc/classes/SurfaceTool.xml b/doc/classes/SurfaceTool.xml
index 25188a80db..e97f9995ee 100644
--- a/doc/classes/SurfaceTool.xml
+++ b/doc/classes/SurfaceTool.xml
@@ -169,6 +169,12 @@
Returns a constructed [ArrayMesh] from current information passed in. If an existing [ArrayMesh] is passed in as an argument, will add an extra surface to the existing [ArrayMesh].
</description>
</method>
+ <method name="commit_to_arrays">
+ <return type="Array">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="create_from">
<return type="void">
</return>
@@ -180,6 +186,18 @@
Creates a vertex array from an existing [Mesh].
</description>
</method>
+ <method name="create_from_blend_shape">
+ <return type="void">
+ </return>
+ <argument index="0" name="existing" type="Mesh">
+ </argument>
+ <argument index="1" name="surface" type="int">
+ </argument>
+ <argument index="2" name="blend_shape" type="String">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="deindex">
<return type="void">
</return>
diff --git a/doc/classes/Tree.xml b/doc/classes/Tree.xml
index b60673bb5b..0272efeecb 100644
--- a/doc/classes/Tree.xml
+++ b/doc/classes/Tree.xml
@@ -271,6 +271,12 @@
Emitted when a cell with the [code]CELL_MODE_CUSTOM[/code] is clicked to be edited.
</description>
</signal>
+ <signal name="empty_rmb">
+ <argument index="0" name="position" type="Vector2">
+ </argument>
+ <description>
+ </description>
+ </signal>
<signal name="empty_tree_rmb_selected">
<argument index="0" name="position" type="Vector2">
</argument>
diff --git a/doc/classes/VehicleWheel.xml b/doc/classes/VehicleWheel.xml
index f8dac82cb5..c3b668c170 100644
--- a/doc/classes/VehicleWheel.xml
+++ b/doc/classes/VehicleWheel.xml
@@ -9,6 +9,12 @@
<tutorials>
</tutorials>
<methods>
+ <method name="get_rpm" qualifiers="const">
+ <return type="float">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="get_skidinfo" qualifiers="const">
<return type="float">
</return>
diff --git a/doc/classes/VisualServer.xml b/doc/classes/VisualServer.xml
index 3563120f0f..3997798cca 100644
--- a/doc/classes/VisualServer.xml
+++ b/doc/classes/VisualServer.xml
@@ -3597,7 +3597,7 @@
get_viewport().set_attach_to_screen_rect(Rect2())
$Viewport.set_attach_to_screen_rect(Rect2(0, 0, 600, 600))
[/codeblock]
- Using this can result in significant optimization, especially on lower-end devices. However, it comes at the cost of having to manage your viewports manually. For a further optimization see, [method set_render_direct_to_screen].
+ Using this can result in significant optimization, especially on lower-end devices. However, it comes at the cost of having to manage your viewports manually. For a further optimization see, [method viewport_set_render_direct_to_screen].
</description>
</method>
<method name="viewport_create">
diff --git a/doc/classes/VisualShader.xml b/doc/classes/VisualShader.xml
index d399f69c96..6d5f53d992 100644
--- a/doc/classes/VisualShader.xml
+++ b/doc/classes/VisualShader.xml
@@ -53,6 +53,22 @@
<description>
</description>
</method>
+ <method name="connect_nodes_forced">
+ <return type="void">
+ </return>
+ <argument index="0" name="type" type="int" enum="VisualShader.Type">
+ </argument>
+ <argument index="1" name="from_node" type="int">
+ </argument>
+ <argument index="2" name="from_port" type="int">
+ </argument>
+ <argument index="3" name="to_node" type="int">
+ </argument>
+ <argument index="4" name="to_port" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="disconnect_nodes">
<return type="void">
</return>
@@ -129,6 +145,12 @@
<description>
</description>
</method>
+ <method name="rebuild">
+ <return type="void">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="remove_node">
<return type="void">
</return>
diff --git a/doc/classes/VisualShaderNodeExpression.xml b/doc/classes/VisualShaderNodeExpression.xml
new file mode 100644
index 0000000000..8a5477280f
--- /dev/null
+++ b/doc/classes/VisualShaderNodeExpression.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="VisualShaderNodeExpression" inherits="VisualShaderNodeGroupBase" category="Core" version="3.2">
+ <brief_description>
+ </brief_description>
+ <description>
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ <method name="build">
+ <return type="void">
+ </return>
+ <description>
+ </description>
+ </method>
+ </methods>
+ <members>
+ <member name="expression" type="String" setter="set_expression" getter="get_expression">
+ </member>
+ </members>
+ <constants>
+ </constants>
+</class>
diff --git a/doc/classes/VisualShaderNodeGroupBase.xml b/doc/classes/VisualShaderNodeGroupBase.xml
new file mode 100644
index 0000000000..37d48956f6
--- /dev/null
+++ b/doc/classes/VisualShaderNodeGroupBase.xml
@@ -0,0 +1,205 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="VisualShaderNodeGroupBase" inherits="VisualShaderNode" category="Core" version="3.2">
+ <brief_description>
+ </brief_description>
+ <description>
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ <method name="add_input_port">
+ <return type="void">
+ </return>
+ <argument index="0" name="id" type="int">
+ </argument>
+ <argument index="1" name="type" type="int">
+ </argument>
+ <argument index="2" name="name" type="String">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="add_output_port">
+ <return type="void">
+ </return>
+ <argument index="0" name="id" type="int">
+ </argument>
+ <argument index="1" name="type" type="int">
+ </argument>
+ <argument index="2" name="name" type="String">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="clear_input_ports">
+ <return type="void">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="clear_output_ports">
+ <return type="void">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_control">
+ <return type="Control">
+ </return>
+ <argument index="0" name="index" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="get_free_input_port_id" qualifiers="const">
+ <return type="int">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_free_output_port_id" qualifiers="const">
+ <return type="int">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_input_port_count" qualifiers="const">
+ <return type="int">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_inputs" qualifiers="const">
+ <return type="String">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_output_port_count" qualifiers="const">
+ <return type="int">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_outputs" qualifiers="const">
+ <return type="String">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_size" qualifiers="const">
+ <return type="Vector2">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="has_input_port" qualifiers="const">
+ <return type="bool">
+ </return>
+ <argument index="0" name="id" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="has_output_port" qualifiers="const">
+ <return type="bool">
+ </return>
+ <argument index="0" name="id" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="remove_input_port">
+ <return type="void">
+ </return>
+ <argument index="0" name="id" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="remove_output_port">
+ <return type="void">
+ </return>
+ <argument index="0" name="id" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="set_control">
+ <return type="void">
+ </return>
+ <argument index="0" name="control" type="Control">
+ </argument>
+ <argument index="1" name="index" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="set_input_port_name">
+ <return type="void">
+ </return>
+ <argument index="0" name="arg0" type="int">
+ </argument>
+ <argument index="1" name="arg1" type="String">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="set_input_port_type">
+ <return type="void">
+ </return>
+ <argument index="0" name="arg0" type="int">
+ </argument>
+ <argument index="1" name="arg1" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="set_inputs">
+ <return type="void">
+ </return>
+ <argument index="0" name="inputs" type="String">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="set_output_port_name">
+ <return type="void">
+ </return>
+ <argument index="0" name="arg0" type="int">
+ </argument>
+ <argument index="1" name="arg1" type="String">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="set_output_port_type">
+ <return type="void">
+ </return>
+ <argument index="0" name="arg0" type="int">
+ </argument>
+ <argument index="1" name="arg1" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="set_outputs">
+ <return type="void">
+ </return>
+ <argument index="0" name="outputs" type="String">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="set_size">
+ <return type="void">
+ </return>
+ <argument index="0" name="size" type="Vector2">
+ </argument>
+ <description>
+ </description>
+ </method>
+ </methods>
+ <constants>
+ </constants>
+</class>
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 7bf6922205..28aa706c22 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -1921,6 +1921,12 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
file->popup_centered_ratio();
} break;
+ case FILE_QUICK_OPEN: {
+
+ quick_open->popup_dialog("Resource", true);
+ quick_open->set_title(TTR("Quick Open..."));
+
+ } break;
case FILE_QUICK_OPEN_SCENE: {
quick_open->popup_dialog("PackedScene", true);
@@ -5695,6 +5701,7 @@ EditorNode::EditorNode() {
p->add_separator();
p->add_submenu_item(TTR("Open Recent"), "RecentScenes", FILE_OPEN_RECENT);
p->add_separator();
+ p->add_shortcut(ED_SHORTCUT("editor/quick_open", TTR("Quick Open..."), KEY_MASK_SHIFT + KEY_MASK_ALT + KEY_O), FILE_QUICK_OPEN);
p->add_shortcut(ED_SHORTCUT("editor/quick_open_scene", TTR("Quick Open Scene..."), KEY_MASK_SHIFT + KEY_MASK_CMD + KEY_O), FILE_QUICK_OPEN_SCENE);
p->add_shortcut(ED_SHORTCUT("editor/quick_open_script", TTR("Quick Open Script..."), KEY_MASK_ALT + KEY_MASK_CMD + KEY_O), FILE_QUICK_OPEN_SCRIPT);
p->add_separator();
diff --git a/editor/editor_node.h b/editor/editor_node.h
index cfe8bf9ec4..6e7b2b2443 100644
--- a/editor/editor_node.h
+++ b/editor/editor_node.h
@@ -146,6 +146,7 @@ private:
FILE_SAVE_OPTIMIZED,
FILE_OPEN_RECENT,
FILE_OPEN_OLD_SCENE,
+ FILE_QUICK_OPEN,
FILE_QUICK_OPEN_SCENE,
FILE_QUICK_OPEN_SCRIPT,
FILE_OPEN_PREV,
diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp
index 8af4ee8017..56fc1f87a5 100644
--- a/editor/editor_plugin.cpp
+++ b/editor/editor_plugin.cpp
@@ -400,6 +400,18 @@ void EditorPlugin::add_control_to_container(CustomControlContainer p_location, C
EditorNode::get_singleton()->get_inspector_dock_addon_area()->add_child(p_control);
} break;
+ case CONTAINER_PROJECT_SETTING_TAB_LEFT: {
+
+ ProjectSettingsEditor::get_singleton()->get_tabs()->add_child(p_control);
+ ProjectSettingsEditor::get_singleton()->get_tabs()->move_child(p_control, 0);
+
+ } break;
+ case CONTAINER_PROJECT_SETTING_TAB_RIGHT: {
+
+ ProjectSettingsEditor::get_singleton()->get_tabs()->add_child(p_control);
+ ProjectSettingsEditor::get_singleton()->get_tabs()->move_child(p_control, 1);
+
+ } break;
}
}
@@ -450,6 +462,12 @@ void EditorPlugin::remove_control_from_container(CustomControlContainer p_locati
EditorNode::get_singleton()->get_inspector_dock_addon_area()->remove_child(p_control);
} break;
+ case CONTAINER_PROJECT_SETTING_TAB_LEFT:
+ case CONTAINER_PROJECT_SETTING_TAB_RIGHT: {
+
+ ProjectSettingsEditor::get_singleton()->get_tabs()->remove_child(p_control);
+
+ } break;
}
}
@@ -863,6 +881,8 @@ void EditorPlugin::_bind_methods() {
BIND_ENUM_CONSTANT(CONTAINER_CANVAS_EDITOR_SIDE_RIGHT);
BIND_ENUM_CONSTANT(CONTAINER_CANVAS_EDITOR_BOTTOM);
BIND_ENUM_CONSTANT(CONTAINER_PROPERTY_EDITOR_BOTTOM);
+ BIND_ENUM_CONSTANT(CONTAINER_PROJECT_SETTING_TAB_LEFT);
+ BIND_ENUM_CONSTANT(CONTAINER_PROJECT_SETTING_TAB_RIGHT);
BIND_ENUM_CONSTANT(DOCK_SLOT_LEFT_UL);
BIND_ENUM_CONSTANT(DOCK_SLOT_LEFT_BL);
diff --git a/editor/editor_plugin.h b/editor/editor_plugin.h
index 2fcc487377..ba4df35e66 100644
--- a/editor/editor_plugin.h
+++ b/editor/editor_plugin.h
@@ -137,7 +137,9 @@ public:
CONTAINER_CANVAS_EDITOR_SIDE_LEFT,
CONTAINER_CANVAS_EDITOR_SIDE_RIGHT,
CONTAINER_CANVAS_EDITOR_BOTTOM,
- CONTAINER_PROPERTY_EDITOR_BOTTOM
+ CONTAINER_PROPERTY_EDITOR_BOTTOM,
+ CONTAINER_PROJECT_SETTING_TAB_LEFT,
+ CONTAINER_PROJECT_SETTING_TAB_RIGHT,
};
enum DockSlot {
diff --git a/editor/plugins/sprite_editor_plugin.cpp b/editor/plugins/sprite_editor_plugin.cpp
index 7642bfaf04..2deb2090e2 100644
--- a/editor/plugins/sprite_editor_plugin.cpp
+++ b/editor/plugins/sprite_editor_plugin.cpp
@@ -327,7 +327,14 @@ void SpriteEditor::_convert_to_mesh_2d_node() {
MeshInstance2D *mesh_instance = memnew(MeshInstance2D);
mesh_instance->set_mesh(mesh);
- EditorNode::get_singleton()->get_scene_tree_dock()->replace_node(node, mesh_instance);
+
+ UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action(TTR("Convert to Mesh2D"));
+ ur->add_do_method(EditorNode::get_singleton()->get_scene_tree_dock(), "replace_node", node, mesh_instance, true, false);
+ ur->add_do_reference(mesh_instance);
+ ur->add_undo_method(EditorNode::get_singleton()->get_scene_tree_dock(), "replace_node", mesh_instance, node, false, false);
+ ur->add_undo_reference(node);
+ ur->commit_action();
}
void SpriteEditor::_convert_to_polygon_2d_node() {
@@ -379,7 +386,13 @@ void SpriteEditor::_convert_to_polygon_2d_node() {
polygon_2d_instance->set_polygon(polygon);
polygon_2d_instance->set_polygons(polys);
- EditorNode::get_singleton()->get_scene_tree_dock()->replace_node(node, polygon_2d_instance);
+ UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action(TTR("Convert to Polygon2D"));
+ ur->add_do_method(EditorNode::get_singleton()->get_scene_tree_dock(), "replace_node", node, polygon_2d_instance, true, false);
+ ur->add_do_reference(polygon_2d_instance);
+ ur->add_undo_method(EditorNode::get_singleton()->get_scene_tree_dock(), "replace_node", polygon_2d_instance, node, false, false);
+ ur->add_undo_reference(node);
+ ur->commit_action();
}
void SpriteEditor::_create_collision_polygon_2d_node() {
@@ -396,7 +409,12 @@ void SpriteEditor::_create_collision_polygon_2d_node() {
CollisionPolygon2D *collision_polygon_2d_instance = memnew(CollisionPolygon2D);
collision_polygon_2d_instance->set_polygon(outline);
- _add_as_sibling_or_child(node, collision_polygon_2d_instance);
+ UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action(TTR("Create CollisionPolygon2D Sibling"));
+ ur->add_do_method(this, "_add_as_sibling_or_child", node, collision_polygon_2d_instance);
+ ur->add_do_reference(collision_polygon_2d_instance);
+ ur->add_undo_method(node != this->get_tree()->get_edited_scene_root() ? node->get_parent() : this->get_tree()->get_edited_scene_root(), "remove_child", collision_polygon_2d_instance);
+ ur->commit_action();
}
}
@@ -425,15 +443,20 @@ void SpriteEditor::_create_light_occluder_2d_node() {
LightOccluder2D *light_occluder_2d_instance = memnew(LightOccluder2D);
light_occluder_2d_instance->set_occluder_polygon(polygon);
- _add_as_sibling_or_child(node, light_occluder_2d_instance);
+ UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action(TTR("Create LightOccluder2D Sibling"));
+ ur->add_do_method(this, "_add_as_sibling_or_child", node, light_occluder_2d_instance);
+ ur->add_do_reference(light_occluder_2d_instance);
+ ur->add_undo_method(node != this->get_tree()->get_edited_scene_root() ? node->get_parent() : this->get_tree()->get_edited_scene_root(), "remove_child", light_occluder_2d_instance);
+ ur->commit_action();
}
}
-void SpriteEditor::_add_as_sibling_or_child(Node2D *p_own_node, Node2D *p_new_node) {
+void SpriteEditor::_add_as_sibling_or_child(Node *p_own_node, Node *p_new_node) {
// Can't make sibling if own node is scene root
if (p_own_node != this->get_tree()->get_edited_scene_root()) {
p_own_node->get_parent()->add_child(p_new_node, true);
- p_new_node->set_transform(p_own_node->get_transform());
+ Object::cast_to<Node2D>(p_new_node)->set_transform(Object::cast_to<Node2D>(p_own_node)->get_transform());
} else {
p_own_node->add_child(p_new_node, true);
}
@@ -534,6 +557,7 @@ void SpriteEditor::_bind_methods() {
ClassDB::bind_method("_debug_uv_draw", &SpriteEditor::_debug_uv_draw);
ClassDB::bind_method("_update_mesh_data", &SpriteEditor::_update_mesh_data);
ClassDB::bind_method("_create_node", &SpriteEditor::_create_node);
+ ClassDB::bind_method("_add_as_sibling_or_child", &SpriteEditor::_add_as_sibling_or_child);
}
SpriteEditor::SpriteEditor() {
diff --git a/editor/plugins/sprite_editor_plugin.h b/editor/plugins/sprite_editor_plugin.h
index 460f5a5707..81be4a19e9 100644
--- a/editor/plugins/sprite_editor_plugin.h
+++ b/editor/plugins/sprite_editor_plugin.h
@@ -84,7 +84,7 @@ class SpriteEditor : public Control {
void _create_collision_polygon_2d_node();
void _create_light_occluder_2d_node();
- void _add_as_sibling_or_child(Node2D *p_own_node, Node2D *p_new_node);
+ void _add_as_sibling_or_child(Node *p_own_node, Node *p_new_node);
protected:
void _node_removed(Node *p_node);
diff --git a/editor/plugins/tile_map_editor_plugin.cpp b/editor/plugins/tile_map_editor_plugin.cpp
index 29a54f815d..772e47ac3a 100644
--- a/editor/plugins/tile_map_editor_plugin.cpp
+++ b/editor/plugins/tile_map_editor_plugin.cpp
@@ -760,7 +760,7 @@ void TileMapEditor::_draw_cell(Control *p_viewport, int p_cell, const Point2i &p
r.position += (r.size + Vector2(spacing, spacing)) * offset;
}
Size2 sc = p_xform.get_scale();
-
+ Size2 cell_size = node->get_cell_size();
Rect2 rect = Rect2();
rect.position = node->map_to_world(p_point) + node->get_cell_draw_offset();
@@ -770,62 +770,25 @@ void TileMapEditor::_draw_cell(Control *p_viewport, int p_cell, const Point2i &p
rect.size = r.size;
}
- if (rect.size.y > rect.size.x) {
- if ((p_flip_h && (p_flip_v || p_transpose)) || (p_flip_v && !p_transpose))
- tile_ofs.y += rect.size.y - rect.size.x;
- } else if (rect.size.y < rect.size.x) {
- if ((p_flip_v && (p_flip_h || p_transpose)) || (p_flip_h && !p_transpose))
- tile_ofs.x += rect.size.x - rect.size.y;
- }
-
if (p_transpose) {
SWAP(tile_ofs.x, tile_ofs.y);
+ rect.position.x += cell_size.x / 2 - rect.size.y / 2;
+ rect.position.y += cell_size.y / 2 - rect.size.x / 2;
+ } else {
+ rect.position += cell_size / 2 - rect.size / 2;
}
+
if (p_flip_h) {
sc.x *= -1.0;
tile_ofs.x *= -1.0;
}
+
if (p_flip_v) {
sc.y *= -1.0;
tile_ofs.y *= -1.0;
}
- if (node->get_tile_origin() == TileMap::TILE_ORIGIN_TOP_LEFT) {
-
- rect.position += tile_ofs;
- } else if (node->get_tile_origin() == TileMap::TILE_ORIGIN_BOTTOM_LEFT) {
- Size2 cell_size = node->get_cell_size();
-
- rect.position += tile_ofs;
-
- if (p_transpose) {
- if (p_flip_h)
- rect.position.x -= cell_size.x;
- else
- rect.position.x += cell_size.x;
- } else {
- if (p_flip_v)
- rect.position.y -= cell_size.y;
- else
- rect.position.y += cell_size.y;
- }
-
- } else if (node->get_tile_origin() == TileMap::TILE_ORIGIN_CENTER) {
- Size2 cell_size = node->get_cell_size();
-
- rect.position += tile_ofs;
-
- if (p_flip_h)
- rect.position.x -= cell_size.x / 2;
- else
- rect.position.x += cell_size.x / 2;
-
- if (p_flip_v)
- rect.position.y -= cell_size.y / 2;
- else
- rect.position.y += cell_size.y / 2;
- }
-
+ rect.position += tile_ofs;
rect.position = p_xform.xform(rect.position);
rect.size *= sc;
diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp
index 8107dee1d4..ce2795f37b 100644
--- a/editor/scene_tree_dock.cpp
+++ b/editor/scene_tree_dock.cpp
@@ -31,6 +31,7 @@
#include "scene_tree_dock.h"
#include "core/io/resource_saver.h"
+#include "core/os/input.h"
#include "core/os/keyboard.h"
#include "core/project_settings.h"
@@ -517,6 +518,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
editor_data->get_undo_redo().add_do_method(editor_selection, "clear");
Node *dupsingle = NULL;
+ List<Node *> editable_children;
for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
@@ -529,6 +531,9 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
Map<const Node *, Node *> duplimap;
Node *dup = node->duplicate_from_editor(duplimap);
+ if (EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(node))
+ editable_children.push_back(dup);
+
ERR_CONTINUE(!dup);
if (selection.size() == 1)
@@ -561,6 +566,9 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
if (dupsingle)
editor->push_item(dupsingle);
+ for (List<Node *>::Element *E = editable_children.front(); E; E = E->next())
+ _toggle_editable_children(E->get());
+
} break;
case TOOL_REPARENT: {
@@ -796,7 +804,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
editable_instance_remove_dialog->popup_centered_minsize();
break;
}
- _toggle_editable_children();
+ _toggle_editable_children(node);
}
}
} break;
@@ -1612,30 +1620,27 @@ void SceneTreeDock::_script_created(Ref<Script> p_script) {
_update_script_button();
}
-void SceneTreeDock::_toggle_editable_children() {
+void SceneTreeDock::_toggle_editable_children_from_selection() {
+
List<Node *> selection = editor_selection->get_selected_node_list();
List<Node *>::Element *e = selection.front();
- if (e) {
- Node *node = e->get();
- if (node) {
- bool editable = EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(node);
- int editable_item_idx = menu->get_item_idx_from_text(TTR("Editable Children"));
- int placeholder_item_idx = menu->get_item_idx_from_text(TTR("Load As Placeholder"));
- editable = !editable;
+ if (e) {
+ _toggle_editable_children(e->get());
+ }
+}
- EditorNode::get_singleton()->get_edited_scene()->set_editable_instance(node, editable);
+void SceneTreeDock::_toggle_editable_children(Node *p_node) {
- menu->set_item_checked(editable_item_idx, editable);
- if (editable) {
- node->set_scene_instance_load_placeholder(false);
- menu->set_item_checked(placeholder_item_idx, false);
- }
+ if (p_node) {
+ bool editable = !EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(p_node);
+ EditorNode::get_singleton()->get_edited_scene()->set_editable_instance(p_node, editable);
+ if (editable)
+ p_node->set_scene_instance_load_placeholder(false);
- SpatialEditor::get_singleton()->update_all_gizmos(node);
+ SpatialEditor::get_singleton()->update_all_gizmos(p_node);
- scene_tree->update_tree();
- }
+ scene_tree->update_tree();
}
}
@@ -1853,7 +1858,7 @@ void SceneTreeDock::_create() {
scene_tree->get_scene_tree()->call_deferred("grab_focus");
}
-void SceneTreeDock::replace_node(Node *p_node, Node *p_by_node, bool p_keep_properties) {
+void SceneTreeDock::replace_node(Node *p_node, Node *p_by_node, bool p_keep_properties, bool p_remove_old) {
Node *n = p_node;
Node *newnode = p_by_node;
@@ -1917,16 +1922,20 @@ void SceneTreeDock::replace_node(Node *p_node, Node *p_by_node, bool p_keep_prop
Node *c = newnode->get_child(i);
c->call("set_transform", c->call("get_transform"));
}
- editor_data->get_undo_redo().clear_history();
+ //p_remove_old was added to support undo
+ if (p_remove_old)
+ editor_data->get_undo_redo().clear_history();
newnode->set_name(newname);
editor->push_item(newnode);
- memdelete(n);
+ if (p_remove_old) {
+ memdelete(n);
- while (to_erase.front()) {
- memdelete(to_erase.front()->get());
- to_erase.pop_front();
+ while (to_erase.front()) {
+ memdelete(to_erase.front()->get());
+ to_erase.pop_front();
+ }
}
}
@@ -2126,7 +2135,7 @@ void SceneTreeDock::_nodes_dragged(Array p_nodes, NodePath p_to, int p_type) {
int to_pos = -1;
_normalize_drop(to_node, to_pos, p_type);
- _do_reparent(to_node, to_pos, nodes, true);
+ _do_reparent(to_node, to_pos, nodes, !Input::get_singleton()->is_key_pressed(KEY_SHIFT));
}
void SceneTreeDock::_add_children_to_popup(Object *p_obj, int p_depth) {
@@ -2475,7 +2484,7 @@ void SceneTreeDock::_bind_methods() {
ClassDB::bind_method(D_METHOD("_input"), &SceneTreeDock::_input);
ClassDB::bind_method(D_METHOD("_nodes_drag_begin"), &SceneTreeDock::_nodes_drag_begin);
ClassDB::bind_method(D_METHOD("_delete_confirm"), &SceneTreeDock::_delete_confirm);
- ClassDB::bind_method(D_METHOD("_toggle_editable_children"), &SceneTreeDock::_toggle_editable_children);
+ ClassDB::bind_method(D_METHOD("_toggle_editable_children_from_selection"), &SceneTreeDock::_toggle_editable_children_from_selection);
ClassDB::bind_method(D_METHOD("_node_prerenamed"), &SceneTreeDock::_node_prerenamed);
ClassDB::bind_method(D_METHOD("_import_subscene"), &SceneTreeDock::_import_subscene);
ClassDB::bind_method(D_METHOD("_selection_changed"), &SceneTreeDock::_selection_changed);
@@ -2495,6 +2504,7 @@ void SceneTreeDock::_bind_methods() {
ClassDB::bind_method(D_METHOD("_feature_profile_changed"), &SceneTreeDock::_feature_profile_changed);
ClassDB::bind_method(D_METHOD("instance"), &SceneTreeDock::instance);
+ ClassDB::bind_method(D_METHOD("replace_node"), &SceneTreeDock::replace_node);
ADD_SIGNAL(MethodInfo("remote_tree_selected"));
}
@@ -2643,7 +2653,7 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSel
editable_instance_remove_dialog = memnew(ConfirmationDialog);
add_child(editable_instance_remove_dialog);
- editable_instance_remove_dialog->connect("confirmed", this, "_toggle_editable_children");
+ editable_instance_remove_dialog->connect("confirmed", this, "_toggle_editable_children_from_selection");
import_subscene_dialog = memnew(EditorSubScene);
add_child(import_subscene_dialog);
diff --git a/editor/scene_tree_dock.h b/editor/scene_tree_dock.h
index e66525d721..9f9e93f2df 100644
--- a/editor/scene_tree_dock.h
+++ b/editor/scene_tree_dock.h
@@ -172,7 +172,8 @@ class SceneTreeDock : public VBoxContainer {
void _delete_confirm();
- void _toggle_editable_children();
+ void _toggle_editable_children_from_selection();
+ void _toggle_editable_children(Node *p_node);
void _node_prerenamed(Node *p_node, const String &p_new_name);
@@ -243,7 +244,7 @@ public:
void show_tab_buttons();
void hide_tab_buttons();
- void replace_node(Node *p_node, Node *p_by_node, bool p_keep_properties = true);
+ void replace_node(Node *p_node, Node *p_by_node, bool p_keep_properties = true, bool p_remove_old = true);
void open_script_dialog(Node *p_for_node);
diff --git a/platform/android/java/src/org/godotengine/godot/Godot.java b/platform/android/java/src/org/godotengine/godot/Godot.java
index 374d40463a..0eeaf0701c 100644
--- a/platform/android/java/src/org/godotengine/godot/Godot.java
+++ b/platform/android/java/src/org/godotengine/godot/Godot.java
@@ -1059,4 +1059,7 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
mProgressFraction.setText(Helpers.getDownloadProgressString(progress.mOverallProgress,
progress.mOverallTotal));
}
+ public void initInputDevices() {
+ mView.initInputDevices();
+ }
}
diff --git a/platform/android/java/src/org/godotengine/godot/GodotView.java b/platform/android/java/src/org/godotengine/godot/GodotView.java
index d7cd5b4360..ab28d9ec33 100644
--- a/platform/android/java/src/org/godotengine/godot/GodotView.java
+++ b/platform/android/java/src/org/godotengine/godot/GodotView.java
@@ -111,6 +111,18 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener {
init(translucent, depth, stencil);
}
+ public void initInputDevices() {
+ /* initially add input devices*/
+ int[] deviceIds = mInputManager.getInputDeviceIds();
+ for (int deviceId : deviceIds) {
+ InputDevice device = mInputManager.getInputDevice(deviceId);
+ if (DEBUG) {
+ Log.v("GodotView", String.format("init() deviceId:%d, Name:%s\n", deviceId, device.getName()));
+ }
+ onInputDeviceAdded(deviceId);
+ }
+ }
+
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouchEvent(MotionEvent event) {
@@ -217,36 +229,42 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener {
// Check if the device has not been already added
if (id < 0) {
InputDevice device = mInputManager.getInputDevice(deviceId);
+ //device can be null if deviceId is not found
+ if (device != null) {
+ int sources = device.getSources();
+ if (((sources & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD) ||
+ ((sources & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK)) {
+ id = joy_devices.size();
+
+ joystick joy = new joystick();
+ joy.device_id = deviceId;
+ joy.name = device.getName();
+ joy.axes = new ArrayList<InputDevice.MotionRange>();
+ joy.hats = new ArrayList<InputDevice.MotionRange>();
+
+ List<InputDevice.MotionRange> ranges = device.getMotionRanges();
+ Collections.sort(ranges, new RangeComparator());
+
+ for (InputDevice.MotionRange range : ranges) {
+ if (range.getAxis() == MotionEvent.AXIS_HAT_X || range.getAxis() == MotionEvent.AXIS_HAT_Y) {
+ joy.hats.add(range);
+ } else {
+ joy.axes.add(range);
+ }
+ }
- id = joy_devices.size();
-
- joystick joy = new joystick();
- joy.device_id = deviceId;
- joy.name = device.getName();
- joy.axes = new ArrayList<InputDevice.MotionRange>();
- joy.hats = new ArrayList<InputDevice.MotionRange>();
-
- List<InputDevice.MotionRange> ranges = device.getMotionRanges();
- Collections.sort(ranges, new RangeComparator());
+ joy_devices.add(joy);
- for (InputDevice.MotionRange range : ranges) {
- if (range.getAxis() == MotionEvent.AXIS_HAT_X || range.getAxis() == MotionEvent.AXIS_HAT_Y) {
- joy.hats.add(range);
- } else {
- joy.axes.add(range);
+ final int device_id = id;
+ final String name = joy.name;
+ queueEvent(new Runnable() {
+ @Override
+ public void run() {
+ GodotLib.joyconnectionchanged(device_id, true, name);
+ }
+ });
}
}
-
- joy_devices.add(joy);
-
- final int device_id = id;
- final String name = joy.name;
- queueEvent(new Runnable() {
- @Override
- public void run() {
- GodotLib.joyconnectionchanged(device_id, true, name);
- }
- });
}
}
@@ -269,6 +287,8 @@ public class GodotView extends GLSurfaceView implements InputDeviceListener {
@Override
public void onInputDeviceChanged(int deviceId) {
+ onInputDeviceRemoved(deviceId);
+ onInputDeviceAdded(deviceId);
}
@Override
public boolean onKeyUp(final int keyCode, KeyEvent event) {
diff --git a/platform/android/java_godot_wrapper.cpp b/platform/android/java_godot_wrapper.cpp
index 101a1d76c6..e92d4437b1 100644
--- a/platform/android/java_godot_wrapper.cpp
+++ b/platform/android/java_godot_wrapper.cpp
@@ -59,6 +59,7 @@ GodotJavaWrapper::GodotJavaWrapper(JNIEnv *p_env, jobject p_godot_instance) {
_get_clipboard = p_env->GetMethodID(cls, "getClipboard", "()Ljava/lang/String;");
_set_clipboard = p_env->GetMethodID(cls, "setClipboard", "(Ljava/lang/String;)V");
_request_permission = p_env->GetMethodID(cls, "requestPermission", "(Ljava/lang/String;)Z");
+ _init_input_devices = p_env->GetMethodID(cls, "initInputDevices", "()V");
}
GodotJavaWrapper::~GodotJavaWrapper() {
@@ -183,3 +184,10 @@ bool GodotJavaWrapper::request_permission(const String &p_name) {
return false;
}
}
+
+void GodotJavaWrapper::init_input_devices() {
+ if (_init_input_devices) {
+ JNIEnv *env = ThreadAndroid::get_env();
+ env->CallVoidMethod(godot_instance, _init_input_devices);
+ }
+}
diff --git a/platform/android/java_godot_wrapper.h b/platform/android/java_godot_wrapper.h
index 438aee019b..be4f109d8c 100644
--- a/platform/android/java_godot_wrapper.h
+++ b/platform/android/java_godot_wrapper.h
@@ -54,6 +54,7 @@ private:
jmethodID _get_clipboard = 0;
jmethodID _set_clipboard = 0;
jmethodID _request_permission = 0;
+ jmethodID _init_input_devices = 0;
public:
GodotJavaWrapper(JNIEnv *p_env, jobject p_godot_instance);
@@ -76,6 +77,7 @@ public:
bool has_set_clipboard();
void set_clipboard(const String &p_text);
bool request_permission(const String &p_name);
+ void init_input_devices();
};
#endif /* !JAVA_GODOT_WRAPPER_H */
diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp
index ff1632cba8..f8076dfd2d 100644
--- a/platform/android/os_android.cpp
+++ b/platform/android/os_android.cpp
@@ -251,6 +251,10 @@ int OS_Android::get_mouse_button_state() const {
}
void OS_Android::set_window_title(const String &p_title) {
+ //This queries/updates the currently connected devices/joypads
+ //Set_window_title is called when initializing the main loop (main.cpp)
+ //therefore this place is found to be suitable (I found no better).
+ godot_java->init_input_devices();
}
void OS_Android::set_video_mode(const VideoMode &p_video_mode, int p_screen) {
diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp
index 3dc0f46676..86be8762d4 100644
--- a/scene/2d/tile_map.cpp
+++ b/scene/2d/tile_map.cpp
@@ -202,47 +202,27 @@ void TileMap::_fix_cell_transform(Transform2D &xform, const Cell &p_cell, const
Size2 s = p_sc;
Vector2 offset = p_offset;
- if (tile_origin == TILE_ORIGIN_BOTTOM_LEFT)
- offset.y += cell_size.y;
- else if (tile_origin == TILE_ORIGIN_CENTER) {
- offset += cell_size / 2;
- }
-
- if (s.y > s.x) {
- if ((p_cell.flip_h && (p_cell.flip_v || p_cell.transpose)) || (p_cell.flip_v && !p_cell.transpose))
- offset.y += s.y - s.x;
- } else if (s.y < s.x) {
- if ((p_cell.flip_v && (p_cell.flip_h || p_cell.transpose)) || (p_cell.flip_h && !p_cell.transpose))
- offset.x += s.x - s.y;
- }
-
if (p_cell.transpose) {
SWAP(xform.elements[0].x, xform.elements[0].y);
SWAP(xform.elements[1].x, xform.elements[1].y);
SWAP(offset.x, offset.y);
SWAP(s.x, s.y);
}
+
if (p_cell.flip_h) {
xform.elements[0].x = -xform.elements[0].x;
xform.elements[1].x = -xform.elements[1].x;
- if (tile_origin == TILE_ORIGIN_TOP_LEFT || tile_origin == TILE_ORIGIN_BOTTOM_LEFT)
- offset.x = s.x - offset.x;
- else if (tile_origin == TILE_ORIGIN_CENTER)
- offset.x = s.x - offset.x / 2;
+ offset.x = s.x - offset.x;
}
+
if (p_cell.flip_v) {
xform.elements[0].y = -xform.elements[0].y;
xform.elements[1].y = -xform.elements[1].y;
- if (tile_origin == TILE_ORIGIN_TOP_LEFT)
- offset.y = s.y - offset.y;
- else if (tile_origin == TILE_ORIGIN_BOTTOM_LEFT) {
- offset.y += s.y;
- } else if (tile_origin == TILE_ORIGIN_CENTER) {
- offset.y += s.y;
- }
+ offset.y = s.y - offset.y;
}
- xform.elements[2].x += offset.x;
- xform.elements[2].y += offset.y;
+
+ offset += cell_size / 2 - s / 2;
+ xform.elements[2] += offset;
}
void TileMap::update_dirty_quadrants() {
@@ -390,64 +370,25 @@ void TileMap::update_dirty_quadrants() {
rect.size.x += fp_adjust;
rect.size.y += fp_adjust;
- if (rect.size.y > rect.size.x) {
- if ((c.flip_h && (c.flip_v || c.transpose)) || (c.flip_v && !c.transpose))
- tile_ofs.y += rect.size.y - rect.size.x;
- } else if (rect.size.y < rect.size.x) {
- if ((c.flip_v && (c.flip_h || c.transpose)) || (c.flip_h && !c.transpose))
- tile_ofs.x += rect.size.x - rect.size.y;
- }
-
- /* rect.size.x+=fp_adjust;
- rect.size.y+=fp_adjust;*/
-
- if (c.transpose)
+ if (c.transpose) {
SWAP(tile_ofs.x, tile_ofs.y);
+ rect.position.x += cell_size.x / 2 - rect.size.y / 2;
+ rect.position.y += cell_size.y / 2 - rect.size.x / 2;
+ } else {
+ rect.position += cell_size / 2 - rect.size / 2;
+ }
if (c.flip_h) {
rect.size.x = -rect.size.x;
tile_ofs.x = -tile_ofs.x;
}
+
if (c.flip_v) {
rect.size.y = -rect.size.y;
tile_ofs.y = -tile_ofs.y;
}
- Vector2 center_ofs;
-
- if (tile_origin == TILE_ORIGIN_TOP_LEFT) {
- rect.position += tile_ofs;
-
- } else if (tile_origin == TILE_ORIGIN_BOTTOM_LEFT) {
-
- rect.position += tile_ofs;
-
- if (c.transpose) {
- if (c.flip_h)
- rect.position.x -= cell_size.x;
- else
- rect.position.x += cell_size.x;
- } else {
- if (c.flip_v)
- rect.position.y -= cell_size.y;
- else
- rect.position.y += cell_size.y;
- }
-
- } else if (tile_origin == TILE_ORIGIN_CENTER) {
-
- rect.position += tile_ofs;
-
- if (c.flip_h)
- rect.position.x -= cell_size.x / 2;
- else
- rect.position.x += cell_size.x / 2;
-
- if (c.flip_v)
- rect.position.y -= cell_size.y / 2;
- else
- rect.position.y += cell_size.y / 2;
- }
+ rect.position += tile_ofs;
Ref<Texture> normal_map = tile_set->tile_get_normal_map(c.id);
Color modulate = tile_set->tile_get_modulate(c.id);
@@ -471,7 +412,7 @@ void TileMap::update_dirty_quadrants() {
Vector2 shape_ofs = shapes[j].shape_transform.get_origin();
- _fix_cell_transform(xform, c, shape_ofs + center_ofs, s);
+ _fix_cell_transform(xform, c, shape_ofs, s);
xform *= shapes[j].shape_transform.untranslated();
@@ -523,7 +464,7 @@ void TileMap::update_dirty_quadrants() {
if (navpoly.is_valid()) {
Transform2D xform;
xform.set_origin(offset.floor() + q.pos);
- _fix_cell_transform(xform, c, npoly_ofs + center_ofs, s);
+ _fix_cell_transform(xform, c, npoly_ofs, s);
int pid = navigation->navpoly_add(navpoly, nav_rel * xform);
@@ -573,7 +514,7 @@ void TileMap::update_dirty_quadrants() {
}
Transform2D navxform;
navxform.set_origin(offset.floor());
- _fix_cell_transform(navxform, c, npoly_ofs + center_ofs, s);
+ _fix_cell_transform(navxform, c, npoly_ofs, s);
vs->canvas_item_set_transform(debug_navigation_item, navxform);
vs->canvas_item_add_triangle_array(debug_navigation_item, indices, vertices, colors);
@@ -593,7 +534,7 @@ void TileMap::update_dirty_quadrants() {
Vector2 occluder_ofs = tile_set->tile_get_occluder_offset(c.id);
Transform2D xform;
xform.set_origin(offset.floor() + q.pos);
- _fix_cell_transform(xform, c, occluder_ofs + center_ofs, s);
+ _fix_cell_transform(xform, c, occluder_ofs, s);
RID orid = VS::get_singleton()->canvas_light_occluder_create();
VS::get_singleton()->canvas_light_occluder_set_transform(orid, get_global_transform() * xform);
diff --git a/scene/3d/arvr_nodes.cpp b/scene/3d/arvr_nodes.cpp
index 52fa96ee4a..4e88948ce2 100644
--- a/scene/3d/arvr_nodes.cpp
+++ b/scene/3d/arvr_nodes.cpp
@@ -127,7 +127,7 @@ Point2 ARVRCamera::unproject_position(const Vector3 &p_pos) const {
return res;
};
-Vector3 ARVRCamera::project_position(const Point2 &p_point) const {
+Vector3 ARVRCamera::project_position(const Point2 &p_point, float p_z_depth) const {
// get our ARVRServer
ARVRServer *arvr_server = ARVRServer::get_singleton();
ERR_FAIL_NULL_V(arvr_server, Vector3());
@@ -135,7 +135,7 @@ Vector3 ARVRCamera::project_position(const Point2 &p_point) const {
Ref<ARVRInterface> arvr_interface = arvr_server->get_primary_interface();
if (arvr_interface.is_null()) {
// we might be in the editor or have VR turned off, just call superclass
- return Camera::project_position(p_point);
+ return Camera::project_position(p_point, p_z_depth);
}
if (!is_inside_tree()) {
@@ -155,7 +155,7 @@ Vector3 ARVRCamera::project_position(const Point2 &p_point) const {
point.y = (1.0 - (p_point.y / viewport_size.y)) * 2.0 - 1.0;
point *= vp_size;
- Vector3 p(point.x, point.y, -get_znear());
+ Vector3 p(point.x, point.y, -p_z_depth);
return get_camera_transform().xform(p);
};
diff --git a/scene/3d/arvr_nodes.h b/scene/3d/arvr_nodes.h
index 0833e18d48..8e735f7110 100644
--- a/scene/3d/arvr_nodes.h
+++ b/scene/3d/arvr_nodes.h
@@ -55,7 +55,7 @@ public:
virtual Vector3 project_local_ray_normal(const Point2 &p_pos) const;
virtual Point2 unproject_position(const Vector3 &p_pos) const;
- virtual Vector3 project_position(const Point2 &p_point) const;
+ virtual Vector3 project_position(const Point2 &p_point, float p_z_depth = 0) const;
virtual Vector<Plane> get_frustum() const;
ARVRCamera();
diff --git a/scene/3d/camera.cpp b/scene/3d/camera.cpp
index e360de5b8e..29002c6701 100644
--- a/scene/3d/camera.cpp
+++ b/scene/3d/camera.cpp
@@ -391,13 +391,17 @@ Point2 Camera::unproject_position(const Vector3 &p_pos) const {
return res;
}
-Vector3 Camera::project_position(const Point2 &p_point) const {
+Vector3 Camera::project_position(const Point2 &p_point, float p_z_depth) const {
if (!is_inside_tree()) {
ERR_EXPLAIN("Camera is not inside scene.");
ERR_FAIL_COND_V(!is_inside_tree(), Vector3());
}
+ if (p_z_depth == 0) {
+ return get_global_transform().origin;
+ }
+
Size2 viewport_size = get_viewport()->get_visible_rect().size;
CameraMatrix cm;
@@ -415,7 +419,7 @@ Vector3 Camera::project_position(const Point2 &p_point) const {
point.y = (1.0 - (p_point.y / viewport_size.y)) * 2.0 - 1.0;
point *= vp_size;
- Vector3 p(point.x, point.y, -near);
+ Vector3 p(point.x, point.y, -p_z_depth);
return get_camera_transform().xform(p);
}
@@ -490,7 +494,7 @@ void Camera::_bind_methods() {
ClassDB::bind_method(D_METHOD("project_ray_origin", "screen_point"), &Camera::project_ray_origin);
ClassDB::bind_method(D_METHOD("unproject_position", "world_point"), &Camera::unproject_position);
ClassDB::bind_method(D_METHOD("is_position_behind", "world_point"), &Camera::is_position_behind);
- ClassDB::bind_method(D_METHOD("project_position", "screen_point"), &Camera::project_position);
+ ClassDB::bind_method(D_METHOD("project_position", "screen_point", "z_depth"), &Camera::project_position, DEFVAL(0));
ClassDB::bind_method(D_METHOD("set_perspective", "fov", "z_near", "z_far"), &Camera::set_perspective);
ClassDB::bind_method(D_METHOD("set_orthogonal", "size", "z_near", "z_far"), &Camera::set_orthogonal);
ClassDB::bind_method(D_METHOD("set_frustum", "size", "offset", "z_near", "z_far"), &Camera::set_frustum);
diff --git a/scene/3d/camera.h b/scene/3d/camera.h
index fe8cb84f0d..cbcefbb0ae 100644
--- a/scene/3d/camera.h
+++ b/scene/3d/camera.h
@@ -143,7 +143,7 @@ public:
virtual Vector3 project_local_ray_normal(const Point2 &p_pos) const;
virtual Point2 unproject_position(const Vector3 &p_pos) const;
bool is_position_behind(const Vector3 &p_pos) const;
- virtual Vector3 project_position(const Point2 &p_point) const;
+ virtual Vector3 project_position(const Point2 &p_point, float p_z_depth = 0) const;
Vector<Vector3> get_near_plane_points() const;
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index 368dea7649..2f23c11748 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -2077,7 +2077,9 @@ Node *Node::_duplicate(int p_flags, Map<const Node *, Node *> *r_duplimap) const
}
}
- node->set_name(get_name());
+ if (get_name() != String()) {
+ node->set_name(get_name());
+ }
#ifdef TOOLS_ENABLED
if ((p_flags & DUPLICATE_FROM_EDITOR) && r_duplimap)