diff options
54 files changed, 508 insertions, 112 deletions
diff --git a/core/io/file_access_network.cpp b/core/io/file_access_network.cpp index 7b2bccdfec..ef886cdb3c 100644 --- a/core/io/file_access_network.cpp +++ b/core/io/file_access_network.cpp @@ -83,7 +83,7 @@ int64_t FileAccessNetworkClient::get_64() { void FileAccessNetworkClient::_thread_func() { - client->set_nodelay(true); + client->set_no_delay(true); while (!quit) { DEBUG_PRINT("SEM WAIT - " + itos(sem->get())); diff --git a/core/io/stream_peer_tcp.cpp b/core/io/stream_peer_tcp.cpp index 9cfa810034..5d008904ff 100644 --- a/core/io/stream_peer_tcp.cpp +++ b/core/io/stream_peer_tcp.cpp @@ -55,6 +55,7 @@ void StreamPeerTCP::_bind_methods() { ClassDB::bind_method(D_METHOD("get_connected_host"), &StreamPeerTCP::get_connected_host); ClassDB::bind_method(D_METHOD("get_connected_port"), &StreamPeerTCP::get_connected_port); ClassDB::bind_method(D_METHOD("disconnect_from_host"), &StreamPeerTCP::disconnect_from_host); + ClassDB::bind_method(D_METHOD("set_no_delay", "enabled"), &StreamPeerTCP::set_no_delay); BIND_ENUM_CONSTANT(STATUS_NONE); BIND_ENUM_CONSTANT(STATUS_CONNECTING); diff --git a/core/io/stream_peer_tcp.h b/core/io/stream_peer_tcp.h index fc84525c5f..8a16d820f2 100644 --- a/core/io/stream_peer_tcp.h +++ b/core/io/stream_peer_tcp.h @@ -65,7 +65,7 @@ public: virtual void disconnect_from_host() = 0; virtual IP_Address get_connected_host() const = 0; virtual uint16_t get_connected_port() const = 0; - virtual void set_nodelay(bool p_enabled) = 0; + virtual void set_no_delay(bool p_enabled) = 0; static Ref<StreamPeerTCP> create_ref(); static StreamPeerTCP *create(); diff --git a/core/os/file_access.cpp b/core/os/file_access.cpp index 368b4ad09d..033b4b12b9 100644 --- a/core/os/file_access.cpp +++ b/core/os/file_access.cpp @@ -479,6 +479,9 @@ void FileAccess::store_double(double p_dest) { uint64_t FileAccess::get_modified_time(const String &p_file) { + if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && PackedData::get_singleton()->has_path(p_file)) + return 0; + FileAccess *fa = create_for_path(p_file); ERR_FAIL_COND_V(!fa, 0); diff --git a/core/script_debugger_remote.cpp b/core/script_debugger_remote.cpp index a297bb738f..41071ace5d 100644 --- a/core/script_debugger_remote.cpp +++ b/core/script_debugger_remote.cpp @@ -598,7 +598,13 @@ void ScriptDebuggerRemote::_send_object_id(ObjectID p_id) { Array send_props; for (int i = 0; i < properties.size(); i++) { const PropertyInfo &pi = properties[i].first; - const Variant &var = properties[i].second; + Variant &var = properties[i].second; + + WeakRef *ref = Object::cast_to<WeakRef>(var); + if (ref) { + var = ref->get_ref(); + } + RES res = var; Array prop; diff --git a/core/variant_call.cpp b/core/variant_call.cpp index e9f7af3f63..2ca435611b 100644 --- a/core/variant_call.cpp +++ b/core/variant_call.cpp @@ -1748,10 +1748,10 @@ void register_variant_methods() { ADDFUNC1R(TRANSFORM2D, TRANSFORM2D, Transform2D, rotated, REAL, "phi", varray()); ADDFUNC1R(TRANSFORM2D, TRANSFORM2D, Transform2D, scaled, VECTOR2, "scale", varray()); ADDFUNC1R(TRANSFORM2D, TRANSFORM2D, Transform2D, translated, VECTOR2, "offset", varray()); - ADDFUNC1R(TRANSFORM2D, TRANSFORM2D, Transform2D, xform, NIL, "v", varray()); - ADDFUNC1R(TRANSFORM2D, TRANSFORM2D, Transform2D, xform_inv, NIL, "v", varray()); - ADDFUNC1R(TRANSFORM2D, TRANSFORM2D, Transform2D, basis_xform, NIL, "v", varray()); - ADDFUNC1R(TRANSFORM2D, TRANSFORM2D, Transform2D, basis_xform_inv, NIL, "v", varray()); + ADDFUNC1R(TRANSFORM2D, NIL, Transform2D, xform, NIL, "v", varray()); + ADDFUNC1R(TRANSFORM2D, NIL, Transform2D, xform_inv, NIL, "v", varray()); + ADDFUNC1R(TRANSFORM2D, VECTOR2, Transform2D, basis_xform, VECTOR2, "v", varray()); + ADDFUNC1R(TRANSFORM2D, VECTOR2, Transform2D, basis_xform_inv, VECTOR2, "v", varray()); ADDFUNC2R(TRANSFORM2D, TRANSFORM2D, Transform2D, interpolate_with, TRANSFORM2D, "transform", REAL, "weight", varray()); ADDFUNC0R(BASIS, BASIS, Basis, inverse, varray()); diff --git a/doc/classes/EditorInterface.xml b/doc/classes/EditorInterface.xml index 4d3b31ae35..61c93becde 100644 --- a/doc/classes/EditorInterface.xml +++ b/doc/classes/EditorInterface.xml @@ -100,6 +100,15 @@ Shows the given property on the given [code]object[/code] in the Editor's Inspector dock. </description> </method> + <method name="is_plugin_enabled" qualifiers="const"> + <return type="bool"> + </return> + <argument index="0" name="plugin" type="String"> + </argument> + <description> + Returns the enabled status of a plugin. The plugin name is the same as its directory name. + </description> + </method> <method name="make_mesh_previews"> <return type="Array"> </return> @@ -155,6 +164,17 @@ <description> </description> </method> + <method name="set_plugin_enabled"> + <return type="void"> + </return> + <argument index="0" name="plugin" type="String"> + </argument> + <argument index="1" name="enabled" type="bool"> + </argument> + <description> + Sets the enabled status of a plugin. The plugin name is the same as its directory name. + </description> + </method> </methods> <constants> </constants> diff --git a/doc/classes/GraphEdit.xml b/doc/classes/GraphEdit.xml index 39d6ebc166..2090155e85 100644 --- a/doc/classes/GraphEdit.xml +++ b/doc/classes/GraphEdit.xml @@ -12,6 +12,42 @@ <demos> </demos> <methods> + <method name="add_valid_connection_type"> + <return type="void"> + </return> + <argument index="0" name="from_type" type="int"> + </argument> + <argument index="1" name="to_type" type="int"> + </argument> + <description> + Makes possible the connection between two different slot types. The type is defined with the [method GraphNode.set_slot] method. + </description> + </method> + <method name="add_valid_left_disconnect_type"> + <return type="void"> + </return> + <argument index="0" name="type" type="int"> + </argument> + <description> + Makes possible to disconnect nodes when dragging from the slot at the left if it has the specified type. + </description> + </method> + <method name="add_valid_right_disconnect_type"> + <return type="void"> + </return> + <argument index="0" name="type" type="int"> + </argument> + <description> + Makes possible to disconnect nodes when dragging from the slot at the right if it has the specified type. + </description> + </method> + <method name="clear_connections"> + <return type="void"> + </return> + <description> + Remove all connections between nodes. + </description> + </method> <method name="connect_node"> <return type="int" enum="Error"> </return> @@ -64,12 +100,53 @@ Return true if the 'from_port' slot of 'from' GraphNode is connected to the 'to_port' slot of 'to' GraphNode. </description> </method> + <method name="is_valid_connection_type" qualifiers="const"> + <return type="bool"> + </return> + <argument index="0" name="from_type" type="int"> + </argument> + <argument index="1" name="to_type" type="int"> + </argument> + <description> + Returns whether it's possible to connect slots of the specified types. + </description> + </method> + <method name="remove_valid_connection_type"> + <return type="void"> + </return> + <argument index="0" name="from_type" type="int"> + </argument> + <argument index="1" name="to_type" type="int"> + </argument> + <description> + Makes it not possible to connect between two different slot types. The type is defined with the [method GraphNode.set_slot] method. + </description> + </method> + <method name="remove_valid_left_disconnect_type"> + <return type="void"> + </return> + <argument index="0" name="type" type="int"> + </argument> + <description> + Removes the possibility to disconnect nodes when dragging from the slot at the left if it has the specified type. + </description> + </method> + <method name="remove_valid_right_disconnect_type"> + <return type="void"> + </return> + <argument index="0" name="type" type="int"> + </argument> + <description> + Removes the possibility to disconnect nodes when dragging from the slot at the right if it has the specified type. + </description> + </method> <method name="set_selected"> <return type="void"> </return> <argument index="0" name="node" type="Node"> </argument> <description> + Sets the specified [code]node[/code] as the one selected. </description> </method> </methods> diff --git a/doc/classes/StreamPeerTCP.xml b/doc/classes/StreamPeerTCP.xml index 37fec62cbc..73e9b97367 100644 --- a/doc/classes/StreamPeerTCP.xml +++ b/doc/classes/StreamPeerTCP.xml @@ -29,6 +29,16 @@ Disconnect from host. </description> </method> + <method name="set_no_delay"> + <return type="void"> + </return> + <argument index="0" name="enabled" type="bool"> + </argument> + <description> + Disable Nagle algorithm to improve latency for small packets. + Note that for applications that send large packets, or need to transfer a lot of data, this can reduce total bandwidth. + </description> + </method> <method name="get_connected_host" qualifiers="const"> <return type="String"> </return> diff --git a/doc/classes/Transform.xml b/doc/classes/Transform.xml index c893903b4f..cf1c9ea032 100644 --- a/doc/classes/Transform.xml +++ b/doc/classes/Transform.xml @@ -143,7 +143,7 @@ <argument index="0" name="v" type="var"> </argument> <description> - Transforms the given vector "v" by this transform. + Transforms the given [Vector3], [Plane], or [AABB] by this transform. </description> </method> <method name="xform_inv"> @@ -152,7 +152,7 @@ <argument index="0" name="v" type="var"> </argument> <description> - Inverse-transforms the given vector "v" by this transform. + Inverse-transforms the given [Vector3], [Plane], or [AABB] by this transform. </description> </method> </methods> diff --git a/doc/classes/Transform2D.xml b/doc/classes/Transform2D.xml index 2a7a8bd97d..e20f48ba14 100644 --- a/doc/classes/Transform2D.xml +++ b/doc/classes/Transform2D.xml @@ -52,18 +52,18 @@ </description> </method> <method name="basis_xform"> - <return type="Transform2D"> + <return type="Vector2"> </return> - <argument index="0" name="v" type="var"> + <argument index="0" name="v" type="Vector2"> </argument> <description> Transforms the given vector by this transform's basis (no translation). </description> </method> <method name="basis_xform_inv"> - <return type="Transform2D"> + <return type="Vector2"> </return> - <argument index="0" name="v" type="var"> + <argument index="0" name="v" type="Vector2"> </argument> <description> Inverse-transforms the given vector by this transform's basis (no translation). @@ -143,21 +143,21 @@ </description> </method> <method name="xform"> - <return type="Transform2D"> + <return type="var"> </return> <argument index="0" name="v" type="var"> </argument> <description> - Transforms the given vector "v" by this transform. + Transforms the given [Vector2] or [Rect2] by this transform. </description> </method> <method name="xform_inv"> - <return type="Transform2D"> + <return type="var"> </return> <argument index="0" name="v" type="var"> </argument> <description> - Inverse-transforms the given vector "v" by this transform. + Inverse-transforms the given [Vector2] or [Rect2] by this transform. </description> </method> </methods> diff --git a/doc/classes/Viewport.xml b/doc/classes/Viewport.xml index 2e89dd9ea3..0698a61529 100644 --- a/doc/classes/Viewport.xml +++ b/doc/classes/Viewport.xml @@ -59,6 +59,7 @@ <argument index="0" name="info" type="int" enum="Viewport.RenderInfo"> </argument> <description> + Get the specific information about the viewport from rendering pipeline. </description> </method> <method name="get_size_override" qualifiers="const"> @@ -182,58 +183,82 @@ </methods> <members> <member name="arvr" type="bool" setter="set_use_arvr" getter="use_arvr"> + If [code]true[/code] the viewport will be used in AR/VR process. Default value: [code]false[/code]. </member> <member name="audio_listener_enable_2d" type="bool" setter="set_as_audio_listener_2d" getter="is_audio_listener_2d"> + If [code]true[/code] the viewport will process 2D audio streams. Default value: [code]false[/code]. </member> <member name="audio_listener_enable_3d" type="bool" setter="set_as_audio_listener" getter="is_audio_listener"> + If [code]true[/code] the viewport will process 3D audio streams. Default value: [code]false[/code]. </member> <member name="canvas_transform" type="Transform2D" setter="set_canvas_transform" getter="get_canvas_transform"> The canvas transform of the viewport, useful for changing the on-screen positions of all child [CanvasItem]s. This is relative to the global canvas transform of the viewport. </member> <member name="debug_draw" type="int" setter="set_debug_draw" getter="get_debug_draw" enum="Viewport.DebugDraw"> + The overlay mode for test rendered geometry in debug purposes. Default value: [code]DEBUG_DRAW_DISABLED[/code]. </member> <member name="disable_3d" type="bool" setter="set_disable_3d" getter="is_3d_disabled"> + If [code]true[/code] the viewport will disable 3D rendering. For actual disabling use [code]usage[/code]. Default value: [code]false[/code]. </member> <member name="global_canvas_transform" type="Transform2D" setter="set_global_canvas_transform" getter="get_global_canvas_transform"> The global canvas transform of the viewport. The canvas transform is relative to this. </member> <member name="gui_disable_input" type="bool" setter="set_disable_input" getter="is_input_disabled"> + If [code]true[/code] the viewport will not receive input event. Default value: [code]false[/code]. </member> <member name="gui_snap_controls_to_pixels" type="bool" setter="set_snap_controls_to_pixels" getter="is_snap_controls_to_pixels_enabled"> + If [code]true[/code] the GUI controls on the viewport will lay pixel perfectly. Default value: [code]true[/code]. </member> <member name="hdr" type="bool" setter="set_hdr" getter="get_hdr"> + If [code]true[/code] the viewport rendering will receive benefits from High Dynamic Range algorithm. Default value: [code]true[/code]. </member> <member name="msaa" type="int" setter="set_msaa" getter="get_msaa" enum="Viewport.MSAA"> + The multisample anti-aliasing mode. Default value: [code]MSAA_DISABLED[/code]. </member> <member name="own_world" type="bool" setter="set_use_own_world" getter="is_using_own_world"> + If [code]true[/code] the viewport will use [World] defined in [code]world[/code] property. Default value: [code]false[/code]. </member> <member name="physics_object_picking" type="bool" setter="set_physics_object_picking" getter="get_physics_object_picking"> + If [code]true[/code] the objects rendered by viewport become subjects of mouse picking process. Default value: [code]false[/code]. </member> <member name="render_target_clear_mode" type="int" setter="set_clear_mode" getter="get_clear_mode" enum="Viewport.ClearMode"> + The clear mode when viewport used as a render target. Default value: [code]CLEAR_MODE_ALWAYS[/code]. </member> <member name="render_target_update_mode" type="int" setter="set_update_mode" getter="get_update_mode" enum="Viewport.UpdateMode"> + The update mode when viewport used as a render target. Default value: [code]UPDATE_WHEN_VISIBLE[/code]. </member> <member name="render_target_v_flip" type="bool" setter="set_vflip" getter="get_vflip"> + If [code]true[/code] the result of rendering will be flipped vertically. Default value: [code]false[/code]. </member> <member name="shadow_atlas_quad_0" type="int" setter="set_shadow_atlas_quadrant_subdiv" getter="get_shadow_atlas_quadrant_subdiv" enum="Viewport.ShadowAtlasQuadrantSubdiv"> + The subdivision amount of first quadrant on shadow atlas. Default value: [code]SHADOW_ATLAS_QUADRANT_SUBDIV_4[/code]. </member> <member name="shadow_atlas_quad_1" type="int" setter="set_shadow_atlas_quadrant_subdiv" getter="get_shadow_atlas_quadrant_subdiv" enum="Viewport.ShadowAtlasQuadrantSubdiv"> + The subdivision amount of second quadrant on shadow atlas. Default value: [code]SHADOW_ATLAS_QUADRANT_SUBDIV_4[/code]. </member> <member name="shadow_atlas_quad_2" type="int" setter="set_shadow_atlas_quadrant_subdiv" getter="get_shadow_atlas_quadrant_subdiv" enum="Viewport.ShadowAtlasQuadrantSubdiv"> + The subdivision amount of third quadrant on shadow atlas. Default value: [code]SHADOW_ATLAS_QUADRANT_SUBDIV_16[/code]. </member> <member name="shadow_atlas_quad_3" type="int" setter="set_shadow_atlas_quadrant_subdiv" getter="get_shadow_atlas_quadrant_subdiv" enum="Viewport.ShadowAtlasQuadrantSubdiv"> + The subdivision amount of fourth quadrant on shadow atlas. Default value: [code]SHADOW_ATLAS_QUADRANT_SUBDIV_64[/code]. </member> <member name="shadow_atlas_size" type="int" setter="set_shadow_atlas_size" getter="get_shadow_atlas_size"> + The resolution of shadow atlas. Both width and height is equal to one value. </member> <member name="size" type="Vector2" setter="set_size" getter="get_size"> + The width and height of viewport. </member> <member name="transparent_bg" type="bool" setter="set_transparent_background" getter="has_transparent_background"> + If [code]true[/code] the viewport should render its background as transparent. Default value: [code]false[/code]. </member> <member name="usage" type="int" setter="set_usage" getter="get_usage" enum="Viewport.Usage"> + The rendering mode of viewport. Default value: [code]USAGE_3D[/code]. </member> <member name="world" type="World" setter="set_world" getter="get_world"> + The custom [World] which can be used as 3D environment source. </member> <member name="world_2d" type="World2D" setter="set_world_2d" getter="get_world_2d"> + The custom [World2D] which can be used as 2D environment source. </member> </members> <signals> @@ -254,6 +279,7 @@ Update the render target only when it is visible. This is the default value. </constant> <constant name="UPDATE_ALWAYS" value="3" enum="UpdateMode"> + Always update the render target. </constant> <constant name="SHADOW_ATLAS_QUADRANT_SUBDIV_DISABLED" value="0" enum="ShadowAtlasQuadrantSubdiv"> </constant> @@ -270,30 +296,42 @@ <constant name="SHADOW_ATLAS_QUADRANT_SUBDIV_1024" value="6" enum="ShadowAtlasQuadrantSubdiv"> </constant> <constant name="SHADOW_ATLAS_QUADRANT_SUBDIV_MAX" value="7" enum="ShadowAtlasQuadrantSubdiv"> + Enum limiter. Do not use it directly. </constant> <constant name="RENDER_INFO_OBJECTS_IN_FRAME" value="0" enum="RenderInfo"> + Amount of objects in frame. </constant> <constant name="RENDER_INFO_VERTICES_IN_FRAME" value="1" enum="RenderInfo"> + Amount of vertices in frame. </constant> <constant name="RENDER_INFO_MATERIAL_CHANGES_IN_FRAME" value="2" enum="RenderInfo"> + Amount of material changes in frame. </constant> <constant name="RENDER_INFO_SHADER_CHANGES_IN_FRAME" value="3" enum="RenderInfo"> + Amount of shader changes in frame. </constant> <constant name="RENDER_INFO_SURFACE_CHANGES_IN_FRAME" value="4" enum="RenderInfo"> + Amount of surface changes in frame. </constant> <constant name="RENDER_INFO_DRAW_CALLS_IN_FRAME" value="5" enum="RenderInfo"> + Amount of draw calls in frame. </constant> <constant name="RENDER_INFO_MAX" value="6" enum="RenderInfo"> + Enum limiter. Do not use it directly. </constant> <constant name="DEBUG_DRAW_DISABLED" value="0" enum="DebugDraw"> + Objects are displayed normally. </constant> <constant name="DEBUG_DRAW_UNSHADED" value="1" enum="DebugDraw"> + Objects are displayed without light information. </constant> <constant name="DEBUG_DRAW_OVERDRAW" value="2" enum="DebugDraw"> </constant> <constant name="DEBUG_DRAW_WIREFRAME" value="3" enum="DebugDraw"> + Objects are displayed in wireframe style. </constant> <constant name="MSAA_DISABLED" value="0" enum="MSAA"> + Multisample anti-aliasing mode disabled. This is the default value. </constant> <constant name="MSAA_2X" value="1" enum="MSAA"> </constant> diff --git a/drivers/unix/stream_peer_tcp_posix.cpp b/drivers/unix/stream_peer_tcp_posix.cpp index ba9481d36b..17112e5ab5 100644 --- a/drivers/unix/stream_peer_tcp_posix.cpp +++ b/drivers/unix/stream_peer_tcp_posix.cpp @@ -304,7 +304,7 @@ Error StreamPeerTCPPosix::read(uint8_t *p_buffer, int p_bytes, int &r_received, return OK; }; -void StreamPeerTCPPosix::set_nodelay(bool p_enabled) { +void StreamPeerTCPPosix::set_no_delay(bool p_enabled) { ERR_FAIL_COND(!is_connected_to_host()); int flag = p_enabled ? 1 : 0; diff --git a/drivers/unix/stream_peer_tcp_posix.h b/drivers/unix/stream_peer_tcp_posix.h index 5770ae48f4..bcebe57771 100644 --- a/drivers/unix/stream_peer_tcp_posix.h +++ b/drivers/unix/stream_peer_tcp_posix.h @@ -77,7 +77,7 @@ public: virtual Status get_status() const; virtual void disconnect_from_host(); - virtual void set_nodelay(bool p_enabled); + virtual void set_no_delay(bool p_enabled); static void make_default(); diff --git a/drivers/windows/stream_peer_tcp_winsock.cpp b/drivers/windows/stream_peer_tcp_winsock.cpp index d6a320fb5e..55775fc231 100644 --- a/drivers/windows/stream_peer_tcp_winsock.cpp +++ b/drivers/windows/stream_peer_tcp_winsock.cpp @@ -332,7 +332,7 @@ Error StreamPeerTCPWinsock::connect_to_host(const IP_Address &p_host, uint16_t p return OK; }; -void StreamPeerTCPWinsock::set_nodelay(bool p_enabled) { +void StreamPeerTCPWinsock::set_no_delay(bool p_enabled) { ERR_FAIL_COND(!is_connected_to_host()); int flag = p_enabled ? 1 : 0; setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int)); diff --git a/drivers/windows/stream_peer_tcp_winsock.h b/drivers/windows/stream_peer_tcp_winsock.h index 9be8414878..a0177d374e 100644 --- a/drivers/windows/stream_peer_tcp_winsock.h +++ b/drivers/windows/stream_peer_tcp_winsock.h @@ -81,7 +81,7 @@ public: static void make_default(); static void cleanup(); - virtual void set_nodelay(bool p_enabled); + virtual void set_no_delay(bool p_enabled); StreamPeerTCPWinsock(); ~StreamPeerTCPWinsock(); diff --git a/editor/editor_file_dialog.cpp b/editor/editor_file_dialog.cpp index f356c16827..22b33cc98f 100644 --- a/editor/editor_file_dialog.cpp +++ b/editor/editor_file_dialog.cpp @@ -458,6 +458,23 @@ void EditorFileDialog::_item_selected(int p_item) { get_ok()->set_disabled(_is_open_should_be_disabled()); } +void EditorFileDialog::_multi_selected(int p_item, bool p_selected) { + + int current = p_item; + if (current < 0 || current >= item_list->get_item_count()) + return; + + Dictionary d = item_list->get_item_metadata(current); + + if (!d["dir"] && p_selected) { + + file->set_text(d["name"]); + _request_single_thumbnail(get_current_dir().plus_file(get_current_file())); + } + + get_ok()->set_disabled(_is_open_should_be_disabled()); +} + void EditorFileDialog::_items_clear_selection() { item_list->unselect_all(); @@ -1290,6 +1307,7 @@ void EditorFileDialog::_bind_methods() { ClassDB::bind_method(D_METHOD("_unhandled_input"), &EditorFileDialog::_unhandled_input); ClassDB::bind_method(D_METHOD("_item_selected"), &EditorFileDialog::_item_selected); + ClassDB::bind_method(D_METHOD("_multi_selected"), &EditorFileDialog::_multi_selected); ClassDB::bind_method(D_METHOD("_items_clear_selection"), &EditorFileDialog::_items_clear_selection); ClassDB::bind_method(D_METHOD("_item_list_item_rmb_selected"), &EditorFileDialog::_item_list_item_rmb_selected); ClassDB::bind_method(D_METHOD("_item_list_rmb_clicked"), &EditorFileDialog::_item_list_rmb_clicked); @@ -1598,6 +1616,7 @@ EditorFileDialog::EditorFileDialog() { connect("confirmed", this, "_action_pressed"); item_list->connect("item_selected", this, "_item_selected", varray(), CONNECT_DEFERRED); + item_list->connect("multi_selected", this, "_multi_selected", varray(), CONNECT_DEFERRED); item_list->connect("item_activated", this, "_item_db_selected", varray()); item_list->connect("nothing_selected", this, "_items_clear_selection"); dir->connect("text_entered", this, "_dir_entered"); diff --git a/editor/editor_file_dialog.h b/editor/editor_file_dialog.h index 05f66eadbf..b1f8f1108c 100644 --- a/editor/editor_file_dialog.h +++ b/editor/editor_file_dialog.h @@ -159,6 +159,7 @@ private: void _recent_selected(int p_idx); void _item_selected(int p_item); + void _multi_selected(int p_item, bool p_selected); void _items_clear_selection(); void _item_dc_selected(int p_item); diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 2f0c41c6e1..98991cd7c0 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -4815,6 +4815,10 @@ EditorNode::EditorNode() { Ref<EditorSceneImporterGLTF> import_gltf; import_gltf.instance(); import_scene->add_importer(import_gltf); + + Ref<EditorSceneImporterESCN> import_escn; + import_escn.instance(); + import_scene->add_importer(import_escn); } Ref<ResourceImporterBitMap> import_bitmap; diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp index 9dd8a7232f..b1a0efaea6 100644 --- a/editor/editor_plugin.cpp +++ b/editor/editor_plugin.cpp @@ -235,6 +235,14 @@ Control *EditorInterface::get_base_control() { return EditorNode::get_singleton()->get_gui_base(); } +void EditorInterface::set_plugin_enabled(const String &p_plugin, bool p_enabled) { + EditorNode::get_singleton()->set_addon_plugin_enabled(p_plugin, p_enabled); +} + +bool EditorInterface::is_plugin_enabled(const String &p_plugin) const { + return EditorNode::get_singleton()->is_addon_plugin_enabled(p_plugin); +} + Error EditorInterface::save_scene() { if (!get_edited_scene_root()) return ERR_CANT_CREATE; @@ -271,6 +279,9 @@ void EditorInterface::_bind_methods() { ClassDB::bind_method(D_METHOD("select_file", "p_file"), &EditorInterface::select_file); ClassDB::bind_method(D_METHOD("get_selected_path"), &EditorInterface::get_selected_path); + ClassDB::bind_method(D_METHOD("set_plugin_enabled", "plugin", "enabled"), &EditorInterface::set_plugin_enabled); + ClassDB::bind_method(D_METHOD("is_plugin_enabled", "plugin"), &EditorInterface::is_plugin_enabled); + ClassDB::bind_method(D_METHOD("save_scene"), &EditorInterface::save_scene); ClassDB::bind_method(D_METHOD("save_scene_as", "path", "with_preview"), &EditorInterface::save_scene_as, DEFVAL(true)); } diff --git a/editor/editor_plugin.h b/editor/editor_plugin.h index 145dccc2d5..3d585120c0 100644 --- a/editor/editor_plugin.h +++ b/editor/editor_plugin.h @@ -90,6 +90,9 @@ public: Control *get_base_control(); + void set_plugin_enabled(const String &p_plugin, bool p_enabled); + bool is_plugin_enabled(const String &p_plugin) const; + Error save_scene(); void save_scene_as(const String &p_scene, bool p_with_preview = true); diff --git a/editor/export_template_manager.cpp b/editor/export_template_manager.cpp index 6cbca3f733..c4ecf3c098 100644 --- a/editor/export_template_manager.cpp +++ b/editor/export_template_manager.cpp @@ -30,6 +30,8 @@ #include "export_template_manager.h" +#include "core/os/input.h" +#include "core/os/keyboard.h" #include "editor_node.h" #include "editor_scale.h" #include "io/json.h" @@ -422,6 +424,11 @@ void ExportTemplateManager::_http_download_templates_completed(int p_status, int void ExportTemplateManager::_begin_template_download(const String &p_url) { + if (Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { + OS::get_singleton()->shell_open(p_url); + return; + } + for (int i = 0; i < template_list->get_child_count(); i++) { BaseButton *b = Object::cast_to<BaseButton>(template_list->get_child(0)); if (b) { @@ -576,7 +583,7 @@ ExportTemplateManager::ExportTemplateManager() { template_downloader->add_child(vbc); ScrollContainer *sc = memnew(ScrollContainer); sc->set_custom_minimum_size(Size2(400, 200) * EDSCALE); - vbc->add_margin_child(TTR("Select mirror from list: "), sc); + vbc->add_margin_child(TTR("Select mirror from list: (Shift+Click: Open in Browser)"), sc); template_list = memnew(VBoxContainer); sc->add_child(template_list); sc->set_enable_v_scroll(true); diff --git a/editor/fileserver/editor_file_server.cpp b/editor/fileserver/editor_file_server.cpp index 56fb7633e7..a218070933 100644 --- a/editor/fileserver/editor_file_server.cpp +++ b/editor/fileserver/editor_file_server.cpp @@ -55,7 +55,7 @@ void EditorFileServer::_subthread_start(void *s) { ClientData *cd = (ClientData *)s; - cd->connection->set_nodelay(true); + cd->connection->set_no_delay(true); uint8_t buf4[8]; Error err = cd->connection->get_data(buf4, 4); if (err != OK) { diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index cc9c9a11d7..8ead8d3982 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -77,7 +77,7 @@ bool FileSystemDock::_create_tree(TreeItem *p_parent, EditorFileSystemDirectory return true; } -void FileSystemDock::_update_tree(bool keep_collapse_state) { +void FileSystemDock::_update_tree(bool keep_collapse_state, bool p_uncollapse_root) { Vector<String> uncollapsed_paths; if (keep_collapse_state) { @@ -129,6 +129,10 @@ void FileSystemDock::_update_tree(bool keep_collapse_state) { ti->set_metadata(0, fave); } + if (p_uncollapse_root) { + uncollapsed_paths.push_back("res://"); + } + _create_tree(root, EditorFileSystem::get_singleton()->get_filesystem(), uncollapsed_paths); tree->ensure_cursor_is_visible(); updating_tree = false; @@ -154,6 +158,7 @@ void FileSystemDock::_notification(int p_what) { } else { tree->set_v_size_flags(SIZE_FILL); + button_tree->hide(); if (!tree->is_visible()) { tree->show(); button_favorite->show(); @@ -163,7 +168,6 @@ void FileSystemDock::_notification(int p_what) { if (!file_list_vb->is_visible()) { file_list_vb->show(); - button_tree->hide(); _update_files(true); } } @@ -204,7 +208,7 @@ void FileSystemDock::_notification(int p_what) { if (EditorFileSystem::get_singleton()->is_scanning()) { _set_scanning_mode(); } else { - _update_tree(false); + _update_tree(false, true); } } break; diff --git a/editor/filesystem_dock.h b/editor/filesystem_dock.h index af80557465..2e86b83efc 100644 --- a/editor/filesystem_dock.h +++ b/editor/filesystem_dock.h @@ -157,7 +157,7 @@ private: bool import_dock_needs_update; bool _create_tree(TreeItem *p_parent, EditorFileSystemDirectory *p_dir, Vector<String> &uncollapsed_paths); - void _update_tree(bool keep_collapse_state); + void _update_tree(bool keep_collapse_state, bool p_uncollapse_root = false); void _update_files(bool p_keep_selection); void _update_file_display_toggle_button(); diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index 060953d36a..44948b8209 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/resource_importer_scene.cpp @@ -46,6 +46,7 @@ #include "scene/resources/box_shape.h" #include "scene/resources/plane_shape.h" #include "scene/resources/ray_shape.h" +#include "scene/resources/scene_format_text.h" #include "scene/resources/sphere_shape.h" uint32_t EditorSceneImporter::get_import_flags() const { @@ -1395,3 +1396,25 @@ ResourceImporterScene *ResourceImporterScene::singleton = NULL; ResourceImporterScene::ResourceImporterScene() { singleton = this; } +/////////////////////////////////////// + +uint32_t EditorSceneImporterESCN::get_import_flags() const { + return IMPORT_SCENE; +} +void EditorSceneImporterESCN::get_extensions(List<String> *r_extensions) const { + r_extensions->push_back("escn"); +} +Node *EditorSceneImporterESCN::import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps, Error *r_err) { + + Error error; + Ref<PackedScene> ps = ResourceFormatLoaderText::singleton->load(p_path, p_path, &error); + ERR_FAIL_COND_V(!ps.is_valid(), NULL); + + Node *scene = ps->instance(); + ERR_FAIL_COND_V(!scene, NULL); + + return scene; +} +Ref<Animation> EditorSceneImporterESCN::import_animation(const String &p_path, uint32_t p_flags, int p_bake_fps) { + ERR_FAIL_V(Ref<Animation>()); +} diff --git a/editor/import/resource_importer_scene.h b/editor/import/resource_importer_scene.h index d5f9d53e91..9c3ec7a29b 100644 --- a/editor/import/resource_importer_scene.h +++ b/editor/import/resource_importer_scene.h @@ -155,4 +155,14 @@ public: ResourceImporterScene(); }; +class EditorSceneImporterESCN : public EditorSceneImporter { + GDCLASS(EditorSceneImporterESCN, EditorSceneImporter); + +public: + virtual uint32_t get_import_flags() const; + virtual void get_extensions(List<String> *r_extensions) const; + virtual Node *import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps, Error *r_err = NULL); + virtual Ref<Animation> import_animation(const String &p_path, uint32_t p_flags, int p_bake_fps); +}; + #endif // RESOURCEIMPORTERSCENE_H diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp index 5e8eb06556..bd2cdf0dda 100644 --- a/editor/plugins/spatial_editor_plugin.cpp +++ b/editor/plugins/spatial_editor_plugin.cpp @@ -3827,9 +3827,6 @@ Object *SpatialEditor::_get_editor_data(Object *p_what) { si->sbox_instance = VisualServer::get_singleton()->instance_create2(selection_box->get_rid(), sp->get_world()->get_scenario()); VS::get_singleton()->instance_geometry_set_cast_shadows_setting(si->sbox_instance, VS::SHADOW_CASTING_SETTING_OFF); - if (Engine::get_singleton()->is_editor_hint()) - editor->call("edit_node", sp); - return si; } diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index 16605f2ebd..da283b16dc 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -152,7 +152,7 @@ private: return ""; } - } else if (mode == MODE_NEW) { + } else { // check if the specified folder is empty, even though this is not an error, it is good to check here d->list_dir_begin(); @@ -174,13 +174,6 @@ private: get_ok()->set_disabled(true); return ""; } - - } else if (d->file_exists("project.godot")) { - - set_message(TTR("Please choose a folder that does not contain a 'project.godot' file."), MESSAGE_ERROR); - memdelete(d); - get_ok()->set_disabled(true); - return ""; } set_message(""); @@ -531,11 +524,17 @@ public: set_title(TTR("Rename Project")); get_ok()->set_text(TTR("Rename")); name_container->show(); + status_rect->hide(); + msg->hide(); + get_ok()->set_disabled(false); ProjectSettings *current = memnew(ProjectSettings); if (current->setup(project_path->get_text(), "")) { set_message(TTR("Couldn't get project.godot in the project path."), MESSAGE_ERROR); + status_rect->show(); + msg->show(); + get_ok()->set_disabled(true); } else if (current->has_setting("application/config/name")) { project_name->set_text(current->get("application/config/name")); } @@ -543,8 +542,6 @@ public: project_name->call_deferred("grab_focus"); create_dir->hide(); - status_rect->hide(); - msg->hide(); } else { @@ -632,7 +629,7 @@ public: project_path->set_h_size_flags(SIZE_EXPAND_FILL); pphb->add_child(project_path); - // status button + // status icon status_rect = memnew(TextureRect); status_rect->set_stretch_mode(TextureRect::STRETCH_KEEP_CENTERED); pphb->add_child(status_rect); diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp index 704ec40e4c..058f517ae9 100644 --- a/editor/project_settings_editor.cpp +++ b/editor/project_settings_editor.cpp @@ -750,7 +750,16 @@ void ProjectSettingsEditor::_item_add() { String catname = category->get_text().strip_edges(); String propname = property->get_text().strip_edges(); - String name = catname != "" ? catname + "/" + propname : propname; + + if (propname.empty()) { + return; + } + + if (catname.empty()) { + catname = "global"; + } + + String name = catname + "/" + propname; undo_redo->create_action(TTR("Add Global Property")); diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index d0fd3763e3..0dc0018224 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -176,7 +176,7 @@ void CSharpLanguage::get_reserved_words(List<String> *p_words) const { "fixed", "float", "for", - "forech", + "foreach", "goto", "if", "implicit", @@ -222,14 +222,17 @@ void CSharpLanguage::get_reserved_words(List<String> *p_words) const { "ushort", "using", "virtual", - "volatile", "void", + "volatile", "while", // Contextual keywords. Not reserved words, but I guess we should include // them because this seems to be used only for syntax highlighting. "add", + "alias", "ascending", + "async", + "await", "by", "descending", "dynamic", @@ -238,10 +241,10 @@ void CSharpLanguage::get_reserved_words(List<String> *p_words) const { "get", "global", "group", - "in", "into", "join", "let", + "nameof", "on", "orderby", "partial", @@ -250,6 +253,7 @@ void CSharpLanguage::get_reserved_words(List<String> *p_words) const { "set", "value", "var", + "when", "where", "yield", 0 diff --git a/modules/mono/mono_gd/gd_mono_assembly.cpp b/modules/mono/mono_gd/gd_mono_assembly.cpp index ba56ed6ed5..ef39b8549d 100644 --- a/modules/mono/mono_gd/gd_mono_assembly.cpp +++ b/modules/mono/mono_gd/gd_mono_assembly.cpp @@ -116,6 +116,37 @@ MonoAssembly *GDMonoAssembly::_preload_hook(MonoAssemblyName *aname, char **asse } } + String name = mono_assembly_name_get_name(aname); + bool has_extension = name.ends_with(".dll"); + + if (has_extension ? name == "mscorlib.dll" : name == "mscorlib") { + GDMonoAssembly **stored_assembly = GDMono::get_singleton()->get_loaded_assembly(has_extension ? name.get_basename() : name); + if (stored_assembly) return (*stored_assembly)->get_assembly(); + + String path; + MonoAssembly *res = NULL; + + for (int i = 0; i < search_dirs.size(); i++) { + const String &search_dir = search_dirs[i]; + + if (has_extension) { + path = search_dir.plus_file(name); + if (FileAccess::exists(path)) { + res = _load_assembly_from(name.get_basename(), path); + break; + } + } else { + path = search_dir.plus_file(name + ".dll"); + if (FileAccess::exists(path)) { + res = _load_assembly_from(name, path); + break; + } + } + } + + if (res) return res; + } + return NULL; } diff --git a/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp b/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp index 6a6ee390cc..18ab616826 100644 --- a/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp +++ b/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp @@ -115,7 +115,7 @@ void AudioStreamPlaybackOGGVorbis::seek(float p_time) { if (!active) return; - if (p_time >= get_length()) { + if (p_time >= vorbis_stream->get_length()) { p_time = 0; } frames_mixed = uint32_t(vorbis_stream->sample_rate * p_time); @@ -123,11 +123,6 @@ void AudioStreamPlaybackOGGVorbis::seek(float p_time) { stb_vorbis_seek(ogg_stream, frames_mixed); } -float AudioStreamPlaybackOGGVorbis::get_length() const { - - return vorbis_stream->length; -} - AudioStreamPlaybackOGGVorbis::~AudioStreamPlaybackOGGVorbis() { if (ogg_alloc.alloc_buffer) { stb_vorbis_close(ogg_stream); @@ -261,6 +256,11 @@ float AudioStreamOGGVorbis::get_loop_offset() const { return loop_offset; } +float AudioStreamOGGVorbis::get_length() const { + + return length; +} + void AudioStreamOGGVorbis::_bind_methods() { ClassDB::bind_method(D_METHOD("_set_data", "data"), &AudioStreamOGGVorbis::set_data); diff --git a/modules/stb_vorbis/audio_stream_ogg_vorbis.h b/modules/stb_vorbis/audio_stream_ogg_vorbis.h index bb01c26902..d7bc7cc0d7 100644 --- a/modules/stb_vorbis/audio_stream_ogg_vorbis.h +++ b/modules/stb_vorbis/audio_stream_ogg_vorbis.h @@ -71,8 +71,6 @@ public: virtual float get_playback_position() const; virtual void seek(float p_time); - virtual float get_length() const; //if supported, otherwise return 0 - AudioStreamPlaybackOGGVorbis() {} ~AudioStreamPlaybackOGGVorbis(); }; @@ -112,6 +110,8 @@ public: void set_data(const PoolVector<uint8_t> &p_data); PoolVector<uint8_t> get_data() const; + virtual float get_length() const; //if supported, otherwise return 0 + AudioStreamOGGVorbis(); virtual ~AudioStreamOGGVorbis(); }; diff --git a/platform/osx/SCsub b/platform/osx/SCsub index 07e633a117..5efe2d0b22 100644 --- a/platform/osx/SCsub +++ b/platform/osx/SCsub @@ -10,6 +10,7 @@ def make_debug(target, source, env): os.system(mpprefix + '/libexec/llvm-' + mpclangver + '/bin/llvm-dsymutil %s -o %s.dSYM' % (target[0], target[0])) else: os.system('dsymutil %s -o %s.dSYM' % (target[0], target[0])) + os.system('strip -u -r %s' % (target[0])) files = [ 'crash_handler_osx.mm', diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 43f2a5cf7d..a2a51f10a7 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -2211,6 +2211,36 @@ String OS_Windows::get_locale() const { return "en"; } +// We need this because GetSystemInfo() is unreliable on WOW64 +// see https://msdn.microsoft.com/en-us/library/windows/desktop/ms724381(v=vs.85).aspx +// Taken from MSDN +typedef BOOL(WINAPI *LPFN_ISWOW64PROCESS)(HANDLE, PBOOL); +LPFN_ISWOW64PROCESS fnIsWow64Process; + +BOOL is_wow64() { + BOOL wow64 = FALSE; + + fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(GetModuleHandle(TEXT("kernel32")), "IsWow64Process"); + + if (fnIsWow64Process) { + if (!fnIsWow64Process(GetCurrentProcess(), &wow64)) { + wow64 = FALSE; + } + } + + return wow64; +} + +int OS_Windows::get_processor_count() const { + SYSTEM_INFO sysinfo; + if (is_wow64()) + GetNativeSystemInfo(&sysinfo); + else + GetSystemInfo(&sysinfo); + + return sysinfo.dwNumberOfProcessors; +} + OS::LatinKeyboardVariant OS_Windows::get_latin_keyboard_variant() const { unsigned long azerty[] = { diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h index c24e35e929..7308650695 100644 --- a/platform/windows/os_windows.h +++ b/platform/windows/os_windows.h @@ -253,6 +253,9 @@ public: virtual String get_executable_path() const; virtual String get_locale() const; + + virtual int get_processor_count() const; + virtual LatinKeyboardVariant get_latin_keyboard_variant() const; virtual void enable_for_stealing_focus(ProcessID pid); diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp index 7a2cbf26bc..eaf72d4dbf 100644 --- a/platform/x11/os_x11.cpp +++ b/platform/x11/os_x11.cpp @@ -1862,8 +1862,12 @@ void OS_X11::process_xevents() { e = event; req = &(e.xselectionrequest); - if (req->target == XA_STRING || req->target == XInternAtom(x11_display, "COMPOUND_TEXT", 0) || - req->target == XInternAtom(x11_display, "UTF8_STRING", 0)) { + if (req->target == XInternAtom(x11_display, "UTF8_STRING", 0) || + req->target == XInternAtom(x11_display, "COMPOUND_TEXT", 0) || + req->target == XInternAtom(x11_display, "TEXT", 0) || + req->target == XA_STRING || + req->target == XInternAtom(x11_display, "text/plain;charset=utf-8", 0) || + req->target == XInternAtom(x11_display, "text/plain", 0)) { CharString clip = OS::get_clipboard().utf8(); XChangeProperty(x11_display, req->requestor, @@ -1876,26 +1880,40 @@ void OS_X11::process_xevents() { respond.xselection.property = req->property; } else if (req->target == XInternAtom(x11_display, "TARGETS", 0)) { - Atom data[2]; - data[0] = XInternAtom(x11_display, "UTF8_STRING", 0); - data[1] = XA_STRING; - XChangeProperty(x11_display, req->requestor, req->property, req->target, - 8, PropModeReplace, (unsigned char *)&data, - sizeof(data)); + Atom data[7]; + data[0] = XInternAtom(x11_display, "TARGETS", 0); + data[1] = XInternAtom(x11_display, "UTF8_STRING", 0); + data[2] = XInternAtom(x11_display, "COMPOUND_TEXT", 0); + data[3] = XInternAtom(x11_display, "TEXT", 0); + data[4] = XA_STRING; + data[5] = XInternAtom(x11_display, "text/plain;charset=utf-8", 0); + data[6] = XInternAtom(x11_display, "text/plain", 0); + + XChangeProperty(x11_display, + req->requestor, + req->property, + XA_ATOM, + 32, + PropModeReplace, + (unsigned char *)&data, + sizeof(data) / sizeof(data[0])); respond.xselection.property = req->property; } else { - printf("No String %x\n", - (int)req->target); + char *targetname = XGetAtomName(x11_display, req->target); + printf("No Target '%s'\n", targetname); + if (targetname) + XFree(targetname); respond.xselection.property = None; } + respond.xselection.type = SelectionNotify; respond.xselection.display = req->display; respond.xselection.requestor = req->requestor; respond.xselection.selection = req->selection; respond.xselection.target = req->target; respond.xselection.time = req->time; - XSendEvent(x11_display, req->requestor, 0, 0, &respond); + XSendEvent(x11_display, req->requestor, True, NoEventMask, &respond); XFlush(x11_display); } break; diff --git a/scene/2d/audio_stream_player_2d.cpp b/scene/2d/audio_stream_player_2d.cpp index b11deb08fd..fc67d28a29 100644 --- a/scene/2d/audio_stream_player_2d.cpp +++ b/scene/2d/audio_stream_player_2d.cpp @@ -54,7 +54,7 @@ void AudioStreamPlayer2D::_mix_audio() { int buffer_size = mix_buffer.size(); //mix - stream_playback->mix(buffer, 1.0, buffer_size); + stream_playback->mix(buffer, pitch_scale, buffer_size); //write all outputs for (int i = 0; i < output_count; i++) { @@ -279,6 +279,13 @@ float AudioStreamPlayer2D::get_volume_db() const { return volume_db; } +void AudioStreamPlayer2D::set_pitch_scale(float p_pitch_scale) { + pitch_scale = p_pitch_scale; +} +float AudioStreamPlayer2D::get_pitch_scale() const { + return pitch_scale; +} + void AudioStreamPlayer2D::play(float p_from_pos) { if (stream_playback.is_valid()) { @@ -419,6 +426,9 @@ void AudioStreamPlayer2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_volume_db", "volume_db"), &AudioStreamPlayer2D::set_volume_db); ClassDB::bind_method(D_METHOD("get_volume_db"), &AudioStreamPlayer2D::get_volume_db); + ClassDB::bind_method(D_METHOD("set_pitch_scale", "pitch_scale"), &AudioStreamPlayer2D::set_pitch_scale); + ClassDB::bind_method(D_METHOD("get_pitch_scale"), &AudioStreamPlayer2D::get_pitch_scale); + ClassDB::bind_method(D_METHOD("play", "from_position"), &AudioStreamPlayer2D::play, DEFVAL(0.0)); ClassDB::bind_method(D_METHOD("seek", "to_position"), &AudioStreamPlayer2D::seek); ClassDB::bind_method(D_METHOD("stop"), &AudioStreamPlayer2D::stop); @@ -448,6 +458,7 @@ void AudioStreamPlayer2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "stream", PROPERTY_HINT_RESOURCE_TYPE, "AudioStream"), "set_stream", "get_stream"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "volume_db", PROPERTY_HINT_RANGE, "-80,24"), "set_volume_db", "get_volume_db"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "pitch_scale", PROPERTY_HINT_RANGE, "0.01,32,0.01"), "set_pitch_scale", "get_pitch_scale"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "playing", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "_set_playing", "is_playing"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "autoplay"), "set_autoplay", "is_autoplay_enabled"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "max_distance", PROPERTY_HINT_RANGE, "1,65536,1"), "set_max_distance", "get_max_distance"); @@ -461,6 +472,7 @@ void AudioStreamPlayer2D::_bind_methods() { AudioStreamPlayer2D::AudioStreamPlayer2D() { volume_db = 0; + pitch_scale = 1.0; autoplay = false; setseek = -1; active = false; diff --git a/scene/2d/audio_stream_player_2d.h b/scene/2d/audio_stream_player_2d.h index 39bc985f58..9ae8e3a518 100644 --- a/scene/2d/audio_stream_player_2d.h +++ b/scene/2d/audio_stream_player_2d.h @@ -70,6 +70,7 @@ private: volatile float setplay; float volume_db; + float pitch_scale; bool autoplay; StringName bus; @@ -98,6 +99,9 @@ public: void set_volume_db(float p_volume); float get_volume_db() const; + void set_pitch_scale(float p_pitch_scale); + float get_pitch_scale() const; + void play(float p_from_pos = 0.0); void seek(float p_seconds); void stop(); diff --git a/scene/3d/audio_stream_player_3d.cpp b/scene/3d/audio_stream_player_3d.cpp index bf3bc42e4e..d448ef024d 100644 --- a/scene/3d/audio_stream_player_3d.cpp +++ b/scene/3d/audio_stream_player_3d.cpp @@ -57,18 +57,18 @@ void AudioStreamPlayer3D::_mix_audio() { //mix if (output_count > 0 || out_of_range_mode == OUT_OF_RANGE_MIX) { - float pitch_scale = 0.0; + float output_pitch_scale = 0.0; if (output_count) { //used for doppler, not realistic but good enough for (int i = 0; i < output_count; i++) { - pitch_scale += outputs[i].pitch_scale; + output_pitch_scale += outputs[i].pitch_scale; } - pitch_scale /= float(output_count); + output_pitch_scale /= float(output_count); } else { - pitch_scale = 1.0; + output_pitch_scale = 1.0; } - stream_playback->mix(buffer, pitch_scale, buffer_size); + stream_playback->mix(buffer, pitch_scale * output_pitch_scale, buffer_size); } //write all outputs @@ -607,6 +607,13 @@ float AudioStreamPlayer3D::get_max_db() const { return max_db; } +void AudioStreamPlayer3D::set_pitch_scale(float p_pitch_scale) { + pitch_scale = p_pitch_scale; +} +float AudioStreamPlayer3D::get_pitch_scale() const { + return pitch_scale; +} + void AudioStreamPlayer3D::play(float p_from_pos) { if (stream_playback.is_valid()) { @@ -832,6 +839,9 @@ void AudioStreamPlayer3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_max_db", "max_db"), &AudioStreamPlayer3D::set_max_db); ClassDB::bind_method(D_METHOD("get_max_db"), &AudioStreamPlayer3D::get_max_db); + ClassDB::bind_method(D_METHOD("set_pitch_scale", "pitch_scale"), &AudioStreamPlayer3D::set_pitch_scale); + ClassDB::bind_method(D_METHOD("get_pitch_scale"), &AudioStreamPlayer3D::get_pitch_scale); + ClassDB::bind_method(D_METHOD("play", "from_position"), &AudioStreamPlayer3D::play, DEFVAL(0.0)); ClassDB::bind_method(D_METHOD("seek", "to_position"), &AudioStreamPlayer3D::seek); ClassDB::bind_method(D_METHOD("stop"), &AudioStreamPlayer3D::stop); @@ -885,6 +895,7 @@ void AudioStreamPlayer3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::REAL, "unit_db", PROPERTY_HINT_RANGE, "-80,80"), "set_unit_db", "get_unit_db"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "unit_size", PROPERTY_HINT_RANGE, "0.1,100,0.1"), "set_unit_size", "get_unit_size"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "max_db", PROPERTY_HINT_RANGE, "-24,6"), "set_max_db", "get_max_db"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "pitch_scale", PROPERTY_HINT_RANGE, "0.01,32,0.01"), "set_pitch_scale", "get_pitch_scale"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "playing", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "_set_playing", "is_playing"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "autoplay"), "set_autoplay", "is_autoplay_enabled"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "max_distance", PROPERTY_HINT_RANGE, "0,65536,1"), "set_max_distance", "get_max_distance"); @@ -921,6 +932,7 @@ AudioStreamPlayer3D::AudioStreamPlayer3D() { unit_size = 1; attenuation_model = ATTENUATION_INVERSE_DISTANCE; max_db = 3; + pitch_scale = 1.0; autoplay = false; setseek = -1; active = false; diff --git a/scene/3d/audio_stream_player_3d.h b/scene/3d/audio_stream_player_3d.h index 9a1f369da2..1fcb83cf21 100644 --- a/scene/3d/audio_stream_player_3d.h +++ b/scene/3d/audio_stream_player_3d.h @@ -106,6 +106,7 @@ private: float unit_db; float unit_size; float max_db; + float pitch_scale; bool autoplay; StringName bus; @@ -153,6 +154,9 @@ public: void set_max_db(float p_boost); float get_max_db() const; + void set_pitch_scale(float p_pitch_scale); + float get_pitch_scale() const; + void play(float p_from_pos = 0.0); void seek(float p_seconds); void stop(); diff --git a/scene/audio/audio_player.cpp b/scene/audio/audio_player.cpp index cf070c2235..766c9acf99 100644 --- a/scene/audio/audio_player.cpp +++ b/scene/audio/audio_player.cpp @@ -45,7 +45,7 @@ void AudioStreamPlayer::_mix_internal(bool p_fadeout) { } //mix - stream_playback->mix(buffer, 1.0, buffer_size); + stream_playback->mix(buffer, pitch_scale, buffer_size); //multiply volume interpolating to avoid clicks if this changes float target_volume = p_fadeout ? -80.0 : volume_db; @@ -177,6 +177,13 @@ float AudioStreamPlayer::get_volume_db() const { return volume_db; } +void AudioStreamPlayer::set_pitch_scale(float p_pitch_scale) { + pitch_scale = p_pitch_scale; +} +float AudioStreamPlayer::get_pitch_scale() const { + return pitch_scale; +} + void AudioStreamPlayer::play(float p_from_pos) { if (stream_playback.is_valid()) { @@ -297,6 +304,9 @@ void AudioStreamPlayer::_bind_methods() { ClassDB::bind_method(D_METHOD("set_volume_db", "volume_db"), &AudioStreamPlayer::set_volume_db); ClassDB::bind_method(D_METHOD("get_volume_db"), &AudioStreamPlayer::get_volume_db); + ClassDB::bind_method(D_METHOD("set_pitch_scale", "pitch_scale"), &AudioStreamPlayer::set_pitch_scale); + ClassDB::bind_method(D_METHOD("get_pitch_scale"), &AudioStreamPlayer::get_pitch_scale); + ClassDB::bind_method(D_METHOD("play", "from_position"), &AudioStreamPlayer::play, DEFVAL(0.0)); ClassDB::bind_method(D_METHOD("seek", "to_position"), &AudioStreamPlayer::seek); ClassDB::bind_method(D_METHOD("stop"), &AudioStreamPlayer::stop); @@ -320,6 +330,7 @@ void AudioStreamPlayer::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "stream", PROPERTY_HINT_RESOURCE_TYPE, "AudioStream"), "set_stream", "get_stream"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "volume_db", PROPERTY_HINT_RANGE, "-80,24"), "set_volume_db", "get_volume_db"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "pitch_scale", PROPERTY_HINT_RANGE, "0.01,32,0.01"), "set_pitch_scale", "get_pitch_scale"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "playing", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "_set_playing", "is_playing"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "autoplay"), "set_autoplay", "is_autoplay_enabled"); ADD_PROPERTY(PropertyInfo(Variant::INT, "mix_target", PROPERTY_HINT_ENUM, "Stereo,Surround,Center"), "set_mix_target", "get_mix_target"); @@ -335,6 +346,7 @@ void AudioStreamPlayer::_bind_methods() { AudioStreamPlayer::AudioStreamPlayer() { mix_volume_db = 0; + pitch_scale = 1.0; volume_db = 0; autoplay = false; setseek = -1; diff --git a/scene/audio/audio_player.h b/scene/audio/audio_player.h index 4fee30c0c2..21189aea6d 100644 --- a/scene/audio/audio_player.h +++ b/scene/audio/audio_player.h @@ -54,6 +54,7 @@ private: volatile bool active; float mix_volume_db; + float pitch_scale; float volume_db; bool autoplay; StringName bus; @@ -81,6 +82,9 @@ public: void set_volume_db(float p_volume); float get_volume_db() const; + void set_pitch_scale(float p_pitch_scale); + float get_pitch_scale() const; + void play(float p_from_pos = 0.0); void seek(float p_seconds); void stop(); diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp index 8b9469021c..9dfd388c3d 100644 --- a/scene/gui/base_button.cpp +++ b/scene/gui/base_button.cpp @@ -311,10 +311,6 @@ void BaseButton::set_disabled(bool p_disabled) { status.disabled = p_disabled; update(); _change_notify("disabled"); - if (p_disabled) - set_focus_mode(FOCUS_NONE); - else - set_focus_mode(enabled_focus_mode); } bool BaseButton::is_disabled() const { diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index 1b5014367b..38ce91a4df 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -1147,9 +1147,18 @@ void GraphEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("is_node_connected", "from", "from_port", "to", "to_port"), &GraphEdit::is_node_connected); ClassDB::bind_method(D_METHOD("disconnect_node", "from", "from_port", "to", "to_port"), &GraphEdit::disconnect_node); ClassDB::bind_method(D_METHOD("get_connection_list"), &GraphEdit::_get_connection_list); + ClassDB::bind_method(D_METHOD("clear_connections"), &GraphEdit::clear_connections); ClassDB::bind_method(D_METHOD("get_scroll_ofs"), &GraphEdit::get_scroll_ofs); ClassDB::bind_method(D_METHOD("set_scroll_ofs", "ofs"), &GraphEdit::set_scroll_ofs); + ClassDB::bind_method(D_METHOD("add_valid_right_disconnect_type", "type"), &GraphEdit::add_valid_right_disconnect_type); + ClassDB::bind_method(D_METHOD("remove_valid_right_disconnect_type", "type"), &GraphEdit::remove_valid_right_disconnect_type); + ClassDB::bind_method(D_METHOD("add_valid_left_disconnect_type", "type"), &GraphEdit::add_valid_left_disconnect_type); + ClassDB::bind_method(D_METHOD("remove_valid_left_disconnect_type", "type"), &GraphEdit::remove_valid_left_disconnect_type); + ClassDB::bind_method(D_METHOD("add_valid_connection_type", "from_type", "to_type"), &GraphEdit::add_valid_connection_type); + ClassDB::bind_method(D_METHOD("remove_valid_connection_type", "from_type", "to_type"), &GraphEdit::remove_valid_connection_type); + ClassDB::bind_method(D_METHOD("is_valid_connection_type", "from_type", "to_type"), &GraphEdit::is_valid_connection_type); + ClassDB::bind_method(D_METHOD("set_zoom", "p_zoom"), &GraphEdit::set_zoom); ClassDB::bind_method(D_METHOD("get_zoom"), &GraphEdit::get_zoom); diff --git a/scene/resources/audio_stream_sample.cpp b/scene/resources/audio_stream_sample.cpp index 93ed700482..b77143cd9d 100644 --- a/scene/resources/audio_stream_sample.cpp +++ b/scene/resources/audio_stream_sample.cpp @@ -77,7 +77,7 @@ void AudioStreamPlaybackSample::seek(float p_time) { if (base->format == AudioStreamSample::FORMAT_IMA_ADPCM) return; //no seeking in ima-adpcm - float max = get_length(); + float max = base->get_length(); if (p_time < 0) { p_time = 0; } else if (p_time >= max) { @@ -390,22 +390,6 @@ void AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, in } } -float AudioStreamPlaybackSample::get_length() const { - - int len = base->data_bytes; - switch (base->format) { - case AudioStreamSample::FORMAT_8_BITS: len /= 1; break; - case AudioStreamSample::FORMAT_16_BITS: len /= 2; break; - case AudioStreamSample::FORMAT_IMA_ADPCM: len *= 2; break; - } - - if (base->stereo) { - len /= 2; - } - - return float(len) / base->mix_rate; -} - AudioStreamPlaybackSample::AudioStreamPlaybackSample() { active = false; @@ -469,6 +453,22 @@ bool AudioStreamSample::is_stereo() const { return stereo; } +float AudioStreamSample::get_length() const { + + int len = data_bytes; + switch (format) { + case AudioStreamSample::FORMAT_8_BITS: len /= 1; break; + case AudioStreamSample::FORMAT_16_BITS: len /= 2; break; + case AudioStreamSample::FORMAT_IMA_ADPCM: len *= 2; break; + } + + if (stereo) { + len /= 2; + } + + return float(len) / mix_rate; +} + void AudioStreamSample::set_data(const PoolVector<uint8_t> &p_data) { AudioServer::get_singleton()->lock(); diff --git a/scene/resources/audio_stream_sample.h b/scene/resources/audio_stream_sample.h index 41754301eb..5fe65c194e 100644 --- a/scene/resources/audio_stream_sample.h +++ b/scene/resources/audio_stream_sample.h @@ -77,8 +77,6 @@ public: virtual void mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames); - virtual float get_length() const; //if supported, otherwise return 0 - AudioStreamPlaybackSample(); }; @@ -137,6 +135,8 @@ public: void set_stereo(bool p_enable); bool is_stereo() const; + virtual float get_length() const; //if supported, otherwise return 0 + void set_data(const PoolVector<uint8_t> &p_data); PoolVector<uint8_t> get_data() const; diff --git a/scene/resources/scene_format_text.cpp b/scene/resources/scene_format_text.cpp index 0faa0dc770..91c801c016 100644 --- a/scene/resources/scene_format_text.cpp +++ b/scene/resources/scene_format_text.cpp @@ -1312,6 +1312,8 @@ Error ResourceFormatLoaderText::rename_dependencies(const String &p_path, const return ria->rename_dependencies(f, p_path, p_map); } +ResourceFormatLoaderText *ResourceFormatLoaderText::singleton = NULL; + Error ResourceFormatLoaderText::convert_file_to_binary(const String &p_src_path, const String &p_dst_path) { Error err; diff --git a/scene/resources/scene_format_text.h b/scene/resources/scene_format_text.h index c014b9bfae..c28ded3d77 100644 --- a/scene/resources/scene_format_text.h +++ b/scene/resources/scene_format_text.h @@ -128,7 +128,9 @@ public: }; class ResourceFormatLoaderText : public ResourceFormatLoader { + public: + static ResourceFormatLoaderText *singleton; virtual Ref<ResourceInteractiveLoader> load_interactive(const String &p_path, const String &p_original_path = "", Error *r_error = NULL); virtual void get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions) const; virtual void get_recognized_extensions(List<String> *p_extensions) const; @@ -138,6 +140,8 @@ public: virtual Error rename_dependencies(const String &p_path, const Map<String, String> &p_map); static Error convert_file_to_binary(const String &p_src_path, const String &p_dst_path); + + ResourceFormatLoaderText() { singleton = this; } }; class ResourceFormatSaverTextInstance { diff --git a/servers/audio/audio_stream.cpp b/servers/audio/audio_stream.cpp index 369dfac042..0ad30987e7 100644 --- a/servers/audio/audio_stream.cpp +++ b/servers/audio/audio_stream.cpp @@ -46,9 +46,9 @@ void AudioStreamPlaybackResampled::_begin_resample() { void AudioStreamPlaybackResampled::mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) { - float target_rate = AudioServer::get_singleton()->get_mix_rate() * p_rate_scale; + float target_rate = AudioServer::get_singleton()->get_mix_rate(); - uint64_t mix_increment = uint64_t((get_stream_sampling_rate() / double(target_rate)) * double(FP_LEN)); + uint64_t mix_increment = uint64_t(((get_stream_sampling_rate() * p_rate_scale) / double(target_rate)) * double(FP_LEN)); for (int i = 0; i < p_frames; i++) { @@ -91,6 +91,13 @@ void AudioStreamPlaybackResampled::mix(AudioFrame *p_buffer, float p_rate_scale, } //////////////////////////////// +void AudioStream::_bind_methods() { + + ClassDB::bind_method(D_METHOD("get_length"), &AudioStream::get_length); +} + +//////////////////////////////// + void AudioStreamRandomPitch::set_audio_stream(const Ref<AudioStream> &p_audio_stream) { audio_stream = p_audio_stream; @@ -136,6 +143,14 @@ String AudioStreamRandomPitch::get_stream_name() const { return "RandomPitch"; } +float AudioStreamRandomPitch::get_length() const { + if (audio_stream.is_valid()) { + return audio_stream->get_length(); + } + + return 0; +} + void AudioStreamRandomPitch::_bind_methods() { ClassDB::bind_method(D_METHOD("set_audio_stream", "stream"), &AudioStreamRandomPitch::set_audio_stream); @@ -209,14 +224,6 @@ void AudioStreamPlaybackRandomPitch::mix(AudioFrame *p_buffer, float p_rate_scal } } -float AudioStreamPlaybackRandomPitch::get_length() const { - if (playing.is_valid()) { - return playing->get_length(); - } - - return 0; -} - AudioStreamPlaybackRandomPitch::~AudioStreamPlaybackRandomPitch() { random_pitch->playbacks.erase(this); } diff --git a/servers/audio/audio_stream.h b/servers/audio/audio_stream.h index a6fb88364f..fda4fc2ccc 100644 --- a/servers/audio/audio_stream.h +++ b/servers/audio/audio_stream.h @@ -50,8 +50,6 @@ public: virtual void seek(float p_time) = 0; virtual void mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) = 0; - - virtual float get_length() const = 0; //if supported, otherwise return 0 }; class AudioStreamPlaybackResampled : public AudioStreamPlayback { @@ -85,9 +83,14 @@ class AudioStream : public Resource { GDCLASS(AudioStream, Resource) OBJ_SAVE_TYPE(AudioStream) //children are all saved as AudioStream, so they can be exchanged +protected: + static void _bind_methods(); + public: virtual Ref<AudioStreamPlayback> instance_playback() = 0; virtual String get_stream_name() const = 0; + + virtual float get_length() const = 0; //if supported, otherwise return 0 }; class AudioStreamPlaybackRandomPitch; @@ -114,6 +117,8 @@ public: virtual Ref<AudioStreamPlayback> instance_playback(); virtual String get_stream_name() const; + virtual float get_length() const; //if supported, otherwise return 0 + AudioStreamRandomPitch(); }; @@ -139,8 +144,6 @@ public: virtual void mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames); - virtual float get_length() const; //if supported, otherwise return 0 - ~AudioStreamPlaybackRandomPitch(); }; diff --git a/servers/audio/effects/audio_effect_reverb.cpp b/servers/audio/effects/audio_effect_reverb.cpp index 204b11746c..162c0a1445 100644 --- a/servers/audio/effects/audio_effect_reverb.cpp +++ b/servers/audio/effects/audio_effect_reverb.cpp @@ -96,7 +96,7 @@ void AudioEffectReverb::set_predelay_msec(float p_msec) { void AudioEffectReverb::set_predelay_feedback(float p_feedback) { - predelay_fb = p_feedback; + predelay_fb = CLAMP(p_feedback, 0, 0.98); } void AudioEffectReverb::set_room_size(float p_size) { @@ -185,7 +185,7 @@ void AudioEffectReverb::_bind_methods() { ADD_GROUP("Predelay", "predelay_"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "predelay_msec", PROPERTY_HINT_RANGE, "20,500,1"), "set_predelay_msec", "get_predelay_msec"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "predelay_feedback", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_predelay_feedback", "get_predelay_feedback"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "predelay_feedback", PROPERTY_HINT_RANGE, "0,0.98,0.01"), "set_predelay_feedback", "get_predelay_feedback"); ADD_GROUP("", ""); ADD_PROPERTY(PropertyInfo(Variant::REAL, "room_size", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_room_size", "get_room_size"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "damping", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_damping", "get_damping"); diff --git a/version.py b/version.py index 4e502bc318..0eff47acdc 100644 --- a/version.py +++ b/version.py @@ -1,6 +1,6 @@ short_name = "godot" name = "Godot Engine" major = 3 -minor = 0 -status = "rc3" +minor = 1 +status = "dev" module_config = "" |