Explorar el Código

Merge pull request #35949 from akien-mga/3.2-cherrypicks

Cherry-picks for the 3.2 branch (future 3.2.1)
Rémi Verschelde hace 5 años
padre
commit
8a0f94a688
Se han modificado 41 ficheros con 281 adiciones y 114 borrados
  1. 3 0
      CHANGELOG.md
  2. 1 0
      doc/classes/AnimationPlayer.xml
  3. 6 1
      doc/classes/Array.xml
  4. 6 1
      doc/classes/BakedLightmap.xml
  5. 20 3
      doc/classes/CheckBox.xml
  6. 20 3
      doc/classes/CheckButton.xml
  7. 12 0
      doc/classes/ColorPickerButton.xml
  8. 8 0
      doc/classes/LinkButton.xml
  9. 11 0
      doc/classes/MenuButton.xml
  10. 13 0
      doc/classes/OptionButton.xml
  11. 15 1
      doc/classes/TextureLayered.xml
  12. 1 1
      doc/classes/ToolButton.xml
  13. 1 0
      doc/classes/Tween.xml
  14. 1 1
      drivers/gles2/shader_compiler_gles2.cpp
  15. 1 1
      drivers/gles3/shader_compiler_gles3.cpp
  16. 2 1
      editor/code_editor.cpp
  17. 32 35
      editor/editor_profiler.cpp
  18. 1 0
      editor/inspector_dock.cpp
  19. 3 3
      editor/plugins/script_editor_plugin.cpp
  20. 1 0
      editor/project_manager.cpp
  21. 1 1
      editor/script_create_dialog.cpp
  22. 11 10
      editor/script_editor_debugger.cpp
  23. 1 1
      modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/NodeExtensions.cs
  24. 2 1
      modules/opensimplex/doc_classes/OpenSimplexNoise.xml
  25. 6 3
      modules/opensimplex/open_simplex_noise.cpp
  26. 6 1
      modules/opensimplex/open_simplex_noise.h
  27. 1 1
      modules/stb_vorbis/audio_stream_ogg_vorbis.cpp
  28. 5 8
      platform/android/export/export.cpp
  29. 1 1
      platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java
  30. 5 0
      platform/javascript/detect.py
  31. 18 0
      platform/osx/detect.py
  32. 20 6
      platform/osx/os_osx.mm
  33. 1 1
      platform/uwp/export/export.cpp
  34. 7 2
      platform/x11/os_x11.cpp
  35. 1 0
      platform/x11/os_x11.h
  36. 8 2
      scene/2d/path_2d.cpp
  37. 0 5
      scene/gui/control.cpp
  38. 8 1
      scene/gui/option_button.cpp
  39. 18 18
      scene/resources/tile_set.cpp
  40. 1 1
      scene/resources/visual_shader.cpp
  41. 2 0
      servers/visual/shader_language.cpp

+ 3 - 0
CHANGELOG.md

@@ -250,6 +250,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 - Drag-and-drop support in the TileSet editor.
 - Ability to attach scripts to nodes by dragging a name from the script list to a node in the scene tree.
 - Icons are now displayed next to code completion items, making their type easier to distinguish.
+- TileMap property `centered_textures` can be used to center textures on their tile, instead of using the tile's top-left corner as position for the texture.
 - "Ignore" flag to ignore specific tiles when autotiling in the TileMap editor.
 - Keyboard shortcuts to rotate tiles in the TileMap editor.
   - Default shortcuts are <kbd>A</kbd> (rotate left), <kbd>S</kbd> (rotate right), <kbd>X</kbd> (flip horizontally), <kbd>Y</kbd> (flip vertically).
@@ -519,6 +520,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
   - Graph lines are now thinner and opaque.
   - Graph line widths are now resized to match the editor scale.
   - Rounded values now display trailing zeroes to make their precision clearer.
+- TileMap support for transform operations on cell textures bigger than the cell size has been reworked to properly support isometric tiles.
+  - Breaks compatibility with some TileMaps from previous Godot versions. An opt-in `compatibility_mode` property can be used to restore the previous behavior.
 - Some TileMap editor options were moved to the toolbar.
 - The TileMap editor now displays coordinate information in the 2D viewport's bottom-left corner.
   - This fixes the TileMap editor width changing when hovering tiles in a small window.

+ 1 - 0
doc/classes/AnimationPlayer.xml

@@ -5,6 +5,7 @@
 	</brief_description>
 	<description>
 		An animation player is used for general-purpose playback of [Animation] resources. It contains a dictionary of animations (referenced by name) and custom blend times between their transitions. Additionally, animations can be played and blended in different channels.
+		[AnimationPlayer] is more suited than [Tween] for animations where you know the final values in advance. For example, fading a screen in and out is more easily done with an [AnimationPlayer] node thanks to the animation tools provided by the editor. That particular example can also be implemented with a [Tween] node, but it requires doing everything by code.
 		Updating the target properties of animations occurs at process time.
 	</description>
 	<tutorials>

+ 6 - 1
doc/classes/Array.xml

@@ -322,7 +322,12 @@
 		<method name="sort">
 			<description>
 				Sorts the array.
-				[b]Note:[/b] strings are sorted in alphabetical, not natural order.
+				[b]Note:[/b] Strings are sorted in alphabetical order (as opposed to natural order). This may lead to unexpected behavior when sorting an array of strings ending with a sequence of numbers. Consider the following example:
+				[codeblock]
+				var strings = ["string1", "string2", "string10", "string11"]
+				strings.sort()
+				print(strings) # Prints [string1, string10, string11, string2]
+				[/codeblock]
 			</description>
 		</method>
 		<method name="sort_custom">

+ 6 - 1
doc/classes/BakedLightmap.xml

@@ -18,7 +18,7 @@
 			<argument index="1" name="create_visual_debug" type="bool" default="false">
 			</argument>
 			<description>
-				Bakes the lightmaps within the currently edited scene.
+				Bakes the lightmaps within the currently edited scene. Returns a [enum BakeError] to signify if the bake was successful, or if unsuccessful, how the bake failed.
 			</description>
 		</method>
 		<method name="debug_bake">
@@ -81,14 +81,19 @@
 			More precise bake mode but can take considerably longer to bake.
 		</constant>
 		<constant name="BAKE_ERROR_OK" value="0" enum="BakeError">
+			Baking was successful.
 		</constant>
 		<constant name="BAKE_ERROR_NO_SAVE_PATH" value="1" enum="BakeError">
+			Returns if no viable save path is found. This can happen where an [member image_path] is not specified or when the save location is invalid.
 		</constant>
 		<constant name="BAKE_ERROR_NO_MESHES" value="2" enum="BakeError">
+			Currently unused.
 		</constant>
 		<constant name="BAKE_ERROR_CANT_CREATE_IMAGE" value="3" enum="BakeError">
+			Returns when the baker cannot save per-mesh textures to file.
 		</constant>
 		<constant name="BAKE_ERROR_USER_ABORTED" value="4" enum="BakeError">
+			Returns if user cancels baking.
 		</constant>
 	</constants>
 </class>

+ 20 - 3
doc/classes/CheckBox.xml

@@ -1,10 +1,10 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <class name="CheckBox" inherits="Button" version="3.2">
 	<brief_description>
-		Binary choice user interface widget.
+		Binary choice user interface widget. See also [CheckButton].
 	</brief_description>
 	<description>
-		A checkbox allows the user to make a binary choice (choosing only one of two possible options).
+		A checkbox allows the user to make a binary choice (choosing only one of two possible options). It's similar to [CheckButton] in functionality, but it has a different apperance. To follow established UX patterns, it's recommended to use CheckBox when toggling it has [b]no[/b] immediate effect on something. For instance, it should be used when toggling it will only do something once a confirmation button is pressed.
 	</description>
 	<tutorials>
 	</tutorials>
@@ -18,41 +18,58 @@
 	</constants>
 	<theme_items>
 		<theme_item name="check_vadjust" type="int" default="0">
-			The vertical offset used when rendering the check icons.
+			The vertical offset used when rendering the check icons (in pixels).
 		</theme_item>
 		<theme_item name="checked" type="Texture">
+			The check icon to display when the [CheckBox] is checked.
 		</theme_item>
 		<theme_item name="disabled" type="StyleBox">
+			The [StyleBox] to display as a background when the [CheckBox] is disabled.
 		</theme_item>
 		<theme_item name="focus" type="StyleBox">
+			The [StyleBox] to display as a background when the [CheckBox] is focused.
 		</theme_item>
 		<theme_item name="font" type="Font">
+			The [Font] to use for the [CheckBox] text.
 		</theme_item>
 		<theme_item name="font_color" type="Color" default="Color( 0.88, 0.88, 0.88, 1 )">
+			The [CheckBox] text's font color.
 		</theme_item>
 		<theme_item name="font_color_disabled" type="Color" default="Color( 0.9, 0.9, 0.9, 0.2 )">
+			The [CheckBox] text's font color when it's disabled.
 		</theme_item>
 		<theme_item name="font_color_hover" type="Color" default="Color( 0.94, 0.94, 0.94, 1 )">
+			The [CheckBox] text's font color when it's hovered.
 		</theme_item>
 		<theme_item name="font_color_hover_pressed" type="Color" default="Color( 1, 1, 1, 1 )">
+			The [CheckBox] text's font color when it's hovered and pressed.
 		</theme_item>
 		<theme_item name="font_color_pressed" type="Color" default="Color( 1, 1, 1, 1 )">
+			The [CheckBox] text's font color when it's pressed.
 		</theme_item>
 		<theme_item name="hover" type="StyleBox">
+			The [StyleBox] to display as a background when the [CheckBox] is hovered.
 		</theme_item>
 		<theme_item name="hover_pressed" type="StyleBox">
+			The [StyleBox] to display as a background when the [CheckBox] is hovered and pressed.
 		</theme_item>
 		<theme_item name="hseparation" type="int" default="4">
+			The separation between the check icon and the text (in pixels).
 		</theme_item>
 		<theme_item name="normal" type="StyleBox">
+			The [StyleBox] to display as a background.
 		</theme_item>
 		<theme_item name="pressed" type="StyleBox">
+			The [StyleBox] to display as a background when the [CheckBox] is pressed.
 		</theme_item>
 		<theme_item name="radio_checked" type="Texture">
+			If the [CheckBox] is configured as a radio button, the icon to display when the [CheckBox] is checked.
 		</theme_item>
 		<theme_item name="radio_unchecked" type="Texture">
+			If the [CheckBox] is configured as a radio button, the icon to display when the [CheckBox] is unchecked.
 		</theme_item>
 		<theme_item name="unchecked" type="Texture">
+			The check icon to display when the [CheckBox] is unchecked.
 		</theme_item>
 	</theme_items>
 </class>

+ 20 - 3
doc/classes/CheckButton.xml

@@ -1,10 +1,10 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <class name="CheckButton" inherits="Button" version="3.2">
 	<brief_description>
-		Checkable button.
+		Checkable button. See also [CheckBox].
 	</brief_description>
 	<description>
-		CheckButton is a toggle button displayed as a check field.
+		CheckButton is a toggle button displayed as a check field. It's similar to [CheckBox] in functionality, but it has a different apperance. To follow established UX patterns, it's recommended to use CheckButton when toggling it has an [b]immediate[/b] effect on something. For instance, it should be used if toggling it enables/disables a setting without requiring the user to press a confirmation button.
 	</description>
 	<tutorials>
 	</tutorials>
@@ -18,41 +18,58 @@
 	</constants>
 	<theme_items>
 		<theme_item name="check_vadjust" type="int" default="0">
-			The vertical offset used when rendering the icons.
+			The vertical offset used when rendering the toggle icons (in pixels).
 		</theme_item>
 		<theme_item name="disabled" type="StyleBox">
+			The [StyleBox] to display as a background when the [CheckButton] is disabled.
 		</theme_item>
 		<theme_item name="focus" type="StyleBox">
+			The [StyleBox] to display as a background when the [CheckButton] is focused.
 		</theme_item>
 		<theme_item name="font" type="Font">
+			The [Font] to use for the [CheckButton] text.
 		</theme_item>
 		<theme_item name="font_color" type="Color" default="Color( 0.88, 0.88, 0.88, 1 )">
+			The [CheckButton] text's font color.
 		</theme_item>
 		<theme_item name="font_color_disabled" type="Color" default="Color( 0.9, 0.9, 0.9, 0.2 )">
+			The [CheckButton] text's font color when it's disabled.
 		</theme_item>
 		<theme_item name="font_color_hover" type="Color" default="Color( 0.94, 0.94, 0.94, 1 )">
+			The [CheckButton] text's font color when it's hovered.
 		</theme_item>
 		<theme_item name="font_color_hover_pressed" type="Color" default="Color( 1, 1, 1, 1 )">
+			The [CheckButton] text's font color when it's hovered and pressed.
 		</theme_item>
 		<theme_item name="font_color_pressed" type="Color" default="Color( 1, 1, 1, 1 )">
+			The [CheckButton] text's font color when it's pressed.
 		</theme_item>
 		<theme_item name="hover" type="StyleBox">
+			The [StyleBox] to display as a background when the [CheckButton] is hovered.
 		</theme_item>
 		<theme_item name="hover_pressed" type="StyleBox">
+			The [StyleBox] to display as a background when the [CheckButton] is hovered and pressed.
 		</theme_item>
 		<theme_item name="hseparation" type="int" default="4">
+			The separation between the toggle icon and the text (in pixels).
 		</theme_item>
 		<theme_item name="normal" type="StyleBox">
+			The [StyleBox] to display as a background.
 		</theme_item>
 		<theme_item name="off" type="Texture">
+			The icon to display when the [CheckButton] is unchecked.
 		</theme_item>
 		<theme_item name="off_disabled" type="Texture">
+			The icon to display when the [CheckButton] is unchecked and disabled.
 		</theme_item>
 		<theme_item name="on" type="Texture">
+			The icon to display when the [CheckButton] is checked.
 		</theme_item>
 		<theme_item name="on_disabled" type="Texture">
+			The icon to display when the [CheckButton] is checked and disabled.
 		</theme_item>
 		<theme_item name="pressed" type="StyleBox">
+			The [StyleBox] to display as a background when the [CheckButton] is pressed.
 		</theme_item>
 	</theme_items>
 </class>

+ 12 - 0
doc/classes/ColorPickerButton.xml

@@ -56,28 +56,40 @@
 	</constants>
 	<theme_items>
 		<theme_item name="bg" type="Texture">
+			The background of the color preview rect on the button.
 		</theme_item>
 		<theme_item name="disabled" type="StyleBox">
+			[StyleBox] used when the [ColorPickerButton] is disabled.
 		</theme_item>
 		<theme_item name="focus" type="StyleBox">
+			[StyleBox] used when the [ColorPickerButton] is focused. It is displayed over the current [StyleBox], so using [StyleBoxEmpty] will just disable the focus visual effect.
 		</theme_item>
 		<theme_item name="font" type="Font">
+			[Font] of the [ColorPickerButton]'s text.
 		</theme_item>
 		<theme_item name="font_color" type="Color" default="Color( 1, 1, 1, 1 )">
+			Default text [Color] of the [ColorPickerButton].
 		</theme_item>
 		<theme_item name="font_color_disabled" type="Color" default="Color( 0.9, 0.9, 0.9, 0.3 )">
+			Text [Color] used when the [ColorPickerButton] is disabled.
 		</theme_item>
 		<theme_item name="font_color_hover" type="Color" default="Color( 1, 1, 1, 1 )">
+			Text [Color] used when the [ColorPickerButton] is being hovered.
 		</theme_item>
 		<theme_item name="font_color_pressed" type="Color" default="Color( 0.8, 0.8, 0.8, 1 )">
+			Text [Color] used when the [ColorPickerButton] is being pressed.
 		</theme_item>
 		<theme_item name="hover" type="StyleBox">
+			[StyleBox] used when the [ColorPickerButton] is being hovered.
 		</theme_item>
 		<theme_item name="hseparation" type="int" default="2">
+			The horizontal space between [ColorPickerButton]'s icon and text.
 		</theme_item>
 		<theme_item name="normal" type="StyleBox">
+			Default [StyleBox] for the [ColorPickerButton].
 		</theme_item>
 		<theme_item name="pressed" type="StyleBox">
+			[StyleBox] used when the [ColorPickerButton] is being pressed.
 		</theme_item>
 	</theme_items>
 </class>

+ 8 - 0
doc/classes/LinkButton.xml

@@ -15,8 +15,10 @@
 		<member name="focus_mode" type="int" setter="set_focus_mode" getter="get_focus_mode" override="true" enum="Control.FocusMode" default="0" />
 		<member name="mouse_default_cursor_shape" type="int" setter="set_default_cursor_shape" getter="get_default_cursor_shape" override="true" enum="Control.CursorShape" default="2" />
 		<member name="text" type="String" setter="set_text" getter="get_text" default="&quot;&quot;">
+			The button's text that will be displayed inside the button's area.
 		</member>
 		<member name="underline" type="int" setter="set_underline_mode" getter="get_underline_mode" enum="LinkButton.UnderlineMode" default="0">
+			Determines when to show the underline. See [enum UnderlineMode] for options.
 		</member>
 	</members>
 	<constants>
@@ -32,16 +34,22 @@
 	</constants>
 	<theme_items>
 		<theme_item name="focus" type="StyleBox">
+			[StyleBox] used when the [LinkButton] is focused. It is displayed over the current [StyleBox], so using [StyleBoxEmpty] will just disable the focus visual effect.
 		</theme_item>
 		<theme_item name="font" type="Font">
+			[Font] of the [LinkButton]'s text.
 		</theme_item>
 		<theme_item name="font_color" type="Color" default="Color( 0.88, 0.88, 0.88, 1 )">
+			Default text [Color] of the [LinkButton].
 		</theme_item>
 		<theme_item name="font_color_hover" type="Color" default="Color( 0.94, 0.94, 0.94, 1 )">
+			Text [Color] used when the [LinkButton] is being hovered.
 		</theme_item>
 		<theme_item name="font_color_pressed" type="Color" default="Color( 1, 1, 1, 1 )">
+			Text [Color] used when the [LinkButton] is being pressed.
 		</theme_item>
 		<theme_item name="underline_spacing" type="int" default="2">
+			The vertical space between the baseline of text and the underline.
 		</theme_item>
 	</theme_items>
 </class>

+ 11 - 0
doc/classes/MenuButton.xml

@@ -48,26 +48,37 @@
 	</constants>
 	<theme_items>
 		<theme_item name="disabled" type="StyleBox">
+			[StyleBox] used when the [MenuButton] is disabled.
 		</theme_item>
 		<theme_item name="focus" type="StyleBox">
+			[StyleBox] used when the [MenuButton] is focused. It is displayed over the current [StyleBox], so using [StyleBoxEmpty] will just disable the focus visual effect.
 		</theme_item>
 		<theme_item name="font" type="Font">
+			[Font] of the [MenuButton]'s text.
 		</theme_item>
 		<theme_item name="font_color" type="Color" default="Color( 0.88, 0.88, 0.88, 1 )">
+			Default text [Color] of the [MenuButton].
 		</theme_item>
 		<theme_item name="font_color_disabled" type="Color" default="Color( 1, 1, 1, 0.3 )">
+			Text [Color] used when the [MenuButton] is disabled.
 		</theme_item>
 		<theme_item name="font_color_hover" type="Color" default="Color( 0.94, 0.94, 0.94, 1 )">
+			Text [Color] used when the [MenuButton] is being hovered.
 		</theme_item>
 		<theme_item name="font_color_pressed" type="Color" default="Color( 1, 1, 1, 1 )">
+			Text [Color] used when the [MenuButton] is being pressed.
 		</theme_item>
 		<theme_item name="hover" type="StyleBox">
+			[StyleBox] used when the [MenuButton] is being hovered.
 		</theme_item>
 		<theme_item name="hseparation" type="int" default="3">
+			The horizontal space between [MenuButton]'s icon and text.
 		</theme_item>
 		<theme_item name="normal" type="StyleBox">
+			Default [StyleBox] for the [MenuButton].
 		</theme_item>
 		<theme_item name="pressed" type="StyleBox">
+			[StyleBox] used when the [MenuButton] is being pressed.
 		</theme_item>
 	</theme_items>
 </class>

+ 13 - 0
doc/classes/OptionButton.xml

@@ -232,30 +232,43 @@
 	</constants>
 	<theme_items>
 		<theme_item name="arrow" type="Texture">
+			The arrow icon to be drawn on the right end of the button.
 		</theme_item>
 		<theme_item name="arrow_margin" type="int" default="2">
+			The horizontal space between the arrow icon and the right edge of the button.
 		</theme_item>
 		<theme_item name="disabled" type="StyleBox">
+			[StyleBox] used when the [OptionButton] is disabled.
 		</theme_item>
 		<theme_item name="focus" type="StyleBox">
+			[StyleBox] used when the [OptionButton] is focused. It is displayed over the current [StyleBox], so using [StyleBoxEmpty] will just disable the focus visual effect.
 		</theme_item>
 		<theme_item name="font" type="Font">
+			[Font] of the [OptionButton]'s text.
 		</theme_item>
 		<theme_item name="font_color" type="Color" default="Color( 0.88, 0.88, 0.88, 1 )">
+			Default text [Color] of the [OptionButton].
 		</theme_item>
 		<theme_item name="font_color_disabled" type="Color" default="Color( 0.9, 0.9, 0.9, 0.2 )">
+			Text [Color] used when the [OptionButton] is disabled.
 		</theme_item>
 		<theme_item name="font_color_hover" type="Color" default="Color( 0.94, 0.94, 0.94, 1 )">
+			Text [Color] used when the [OptionButton] is being hovered.
 		</theme_item>
 		<theme_item name="font_color_pressed" type="Color" default="Color( 1, 1, 1, 1 )">
+			Text [Color] used when the [OptionButton] is being pressed.
 		</theme_item>
 		<theme_item name="hover" type="StyleBox">
+			[StyleBox] used when the [OptionButton] is being hovered.
 		</theme_item>
 		<theme_item name="hseparation" type="int" default="2">
+			The horizontal space between [OptionButton]'s icon and text.
 		</theme_item>
 		<theme_item name="normal" type="StyleBox">
+			Default [StyleBox] for the [OptionButton].
 		</theme_item>
 		<theme_item name="pressed" type="StyleBox">
+			[StyleBox] used when the [OptionButton] is being pressed.
 		</theme_item>
 	</theme_items>
 </class>

+ 15 - 1
doc/classes/TextureLayered.xml

@@ -4,7 +4,7 @@
 		Base class for 3D texture types.
 	</brief_description>
 	<description>
-		Base class for [Texture3D] and [TextureArray]. Cannot be used directly.
+		Base class for [Texture3D] and [TextureArray]. Cannot be used directly, but contains all the functions necessary for accessing and using [Texture3D] and [TextureArray]. Data is set on a per-layer basis. For [Texture3D]s, the layer sepcifies the depth or Z-index, they can be treated as a bunch of 2D slices. Similarly, for [TextureArray]s, the layer specifies the array layer.
 	</description>
 	<tutorials>
 	</tutorials>
@@ -23,24 +23,28 @@
 			<argument index="4" name="flags" type="int" default="4">
 			</argument>
 			<description>
+				Creates the [Texture3D] or [TextureArray] with specified [code]width[/code], [code]height[/code], and [code]depth[/code]. See [enum Image.Format] for [code]format[/code] options. See [enum Flags] enumerator for [code]flags[/code] options.
 			</description>
 		</method>
 		<method name="get_depth" qualifiers="const">
 			<return type="int">
 			</return>
 			<description>
+				Returns the depth of the texture. Depth is the 3rd dimension (typically Z-axis).
 			</description>
 		</method>
 		<method name="get_format" qualifiers="const">
 			<return type="int" enum="Image.Format">
 			</return>
 			<description>
+				Returns the current format being used by this texture. See [enum Image.Format] for details.
 			</description>
 		</method>
 		<method name="get_height" qualifiers="const">
 			<return type="int">
 			</return>
 			<description>
+				Returns the height of the texture. Height is typically represented by the Y-axis.
 			</description>
 		</method>
 		<method name="get_layer_data" qualifiers="const">
@@ -49,12 +53,14 @@
 			<argument index="0" name="layer" type="int">
 			</argument>
 			<description>
+				Returns an [Image] resource with the data from specified [code]layer[/code].
 			</description>
 		</method>
 		<method name="get_width" qualifiers="const">
 			<return type="int">
 			</return>
 			<description>
+				Returns the width of the texture. Width is typically represented by the X-axis.
 			</description>
 		</method>
 		<method name="set_data_partial">
@@ -71,6 +77,7 @@
 			<argument index="4" name="mipmap" type="int" default="0">
 			</argument>
 			<description>
+				Partially sets the data for a specified [code]layer[/code] by overwriting using the data of the specified [code]image[/code]. [code]x_offset[/code] and [code]y_offset[/code] determine where the [Image] is "stamped" over the texture. The [code]image[/code] must fit within the texture.
 			</description>
 		</method>
 		<method name="set_layer_data">
@@ -81,23 +88,30 @@
 			<argument index="1" name="layer" type="int">
 			</argument>
 			<description>
+				Sets the data for the specified layer. Data takes the form of a 2-dimensional [Image] resource.
 			</description>
 		</method>
 	</methods>
 	<members>
 		<member name="data" type="Dictionary" setter="_set_data" getter="_get_data" default="{&quot;depth&quot;: 0,&quot;flags&quot;: 4,&quot;format&quot;: 37,&quot;height&quot;: 0,&quot;layers&quot;: [  ],&quot;width&quot;: 0}">
+			Returns a dictionary with all the data used by this texture.
 		</member>
 		<member name="flags" type="int" setter="set_flags" getter="get_flags" default="4">
+			Specifies which [enum Flags] apply to this texture.
 		</member>
 	</members>
 	<constants>
 		<constant name="FLAG_MIPMAPS" value="1" enum="Flags">
+			Texture will generate mipmaps on creation.
 		</constant>
 		<constant name="FLAG_REPEAT" value="2" enum="Flags">
+			Texture will repeat when UV used is outside the 0-1 range.
 		</constant>
 		<constant name="FLAG_FILTER" value="4" enum="Flags">
+			Use filtering when reading from texture. Filtering smooths out pixels. Turning filtering off is slightly faster and more appropriate when you need access to individual pixels.
 		</constant>
 		<constant name="FLAGS_DEFAULT" value="4" enum="Flags">
+			Equivalent to [constant FLAG_FILTER].
 		</constant>
 	</constants>
 </class>

+ 1 - 1
doc/classes/ToolButton.xml

@@ -24,7 +24,7 @@
 			[StyleBox] used when the [ToolButton] is disabled.
 		</theme_item>
 		<theme_item name="focus" type="StyleBox">
-			[StyleBox] used when the [ToolButton] is focused. It is displayed over the current [StyleBox], so using [StyleboxEmpty] will just disable the focus visual effect.
+			[StyleBox] used when the [ToolButton] is focused. It is displayed over the current [StyleBox], so using [StyleBoxEmpty] will just disable the focus visual effect.
 		</theme_item>
 		<theme_item name="font" type="Font">
 			[Font] of the [ToolButton]'s text.

+ 1 - 0
doc/classes/Tween.xml

@@ -5,6 +5,7 @@
 	</brief_description>
 	<description>
 		Tweens are useful for animations requiring a numerical property to be interpolated over a range of values. The name [i]tween[/i] comes from [i]in-betweening[/i], an animation technique where you specify [i]keyframes[/i] and the computer interpolates the frames that appear between them.
+		[Tween] is more suited than [AnimationPlayer] for animations where you don't know the final values in advance. For example, interpolating a dynamically-chosen camera zoom value is best done with a [Tween] node; it would be difficult to do the same thing with an [AnimationPlayer] node.
 		Here is a brief usage example that causes a 2D node to move smoothly between two positions:
 		[codeblock]
 		var tween = get_node("Tween")

+ 1 - 1
drivers/gles2/shader_compiler_gles2.cpp

@@ -80,7 +80,7 @@ static String _opstr(SL::Operator p_op) {
 
 static String _mkid(const String &p_id) {
 
-	String id = "m_" + p_id;
+	String id = "m_" + p_id.replace("__", "_dus_");
 	return id.replace("__", "_dus_"); //doubleunderscore is reserved in glsl
 }
 

+ 1 - 1
drivers/gles3/shader_compiler_gles3.cpp

@@ -166,7 +166,7 @@ static String _opstr(SL::Operator p_op) {
 
 static String _mkid(const String &p_id) {
 
-	String id = "m_" + p_id;
+	String id = "m_" + p_id.replace("__", "_dus_");
 	return id.replace("__", "_dus_"); //doubleunderscore is reserved in glsl
 }
 

+ 2 - 1
editor/code_editor.cpp

@@ -277,7 +277,8 @@ void FindReplaceBar::_replace_all() {
 	}
 
 	text_edit->set_v_scroll(vsval);
-	set_error(vformat(TTR("Replaced %d occurrence(s)."), rc));
+	matches_label->add_color_override("font_color", rc > 0 ? get_color("font_color", "Label") : get_color("error_color", "Editor"));
+	matches_label->set_text(vformat(TTR("%d replaced."), rc));
 
 	text_edit->call_deferred("connect", "text_changed", this, "_editor_text_changed");
 	results_count = -1;

+ 32 - 35
editor/editor_profiler.cpp

@@ -102,26 +102,28 @@ void EditorProfiler::clear() {
 }
 
 static String _get_percent_txt(float p_value, float p_total) {
-	if (p_total == 0)
+	if (p_total == 0) {
 		p_total = 0.00001;
+	}
+
 	return String::num((p_value / p_total) * 100, 1) + "%";
 }
 
 String EditorProfiler::_get_time_as_text(const Metric &m, float p_time, int p_calls) {
 
-	int dmode = display_mode->get_selected();
+	const int dmode = display_mode->get_selected();
 
 	if (dmode == DISPLAY_FRAME_TIME) {
-		return rtos(p_time);
+		return rtos(p_time * 1000).pad_decimals(2) + " ms";
 	} else if (dmode == DISPLAY_AVERAGE_TIME) {
-		if (p_calls == 0)
-			return "0";
-		else
-			return rtos(p_time / p_calls);
+		if (p_calls == 0) {
+			return "0.00 ms";
+		} else {
+			return rtos((p_time / p_calls) * 1000).pad_decimals(2) + " ms";
+		}
 	} else if (dmode == DISPLAY_FRAME_PERCENT) {
 		return _get_percent_txt(p_time, m.frame_time);
 	} else if (dmode == DISPLAY_PHYSICS_FRAME_PERCENT) {
-
 		return _get_percent_txt(p_time, m.physics_frame_time);
 	}
 
@@ -163,12 +165,10 @@ void EditorProfiler::_item_edited() {
 
 void EditorProfiler::_update_plot() {
 
-	int w = graph->get_size().width;
-	int h = graph->get_size().height;
-
+	const int w = graph->get_size().width;
+	const int h = graph->get_size().height;
 	bool reset_texture = false;
-
-	int desired_len = w * h * 4;
+	const int desired_len = w * h * 4;
 
 	if (graph_image.size() != desired_len) {
 		reset_texture = true;
@@ -176,18 +176,19 @@ void EditorProfiler::_update_plot() {
 	}
 
 	PoolVector<uint8_t>::Write wr = graph_image.write();
+	const Color background_color = get_color("dark_color_2", "Editor");
 
-	//clear
+	// Clear the previous frame and set the background color.
 	for (int i = 0; i < desired_len; i += 4) {
-		wr[i + 0] = 0;
-		wr[i + 1] = 0;
-		wr[i + 2] = 0;
+		wr[i + 0] = Math::fast_ftoi(background_color.r * 255);
+		wr[i + 1] = Math::fast_ftoi(background_color.g * 255);
+		wr[i + 2] = Math::fast_ftoi(background_color.b * 255);
 		wr[i + 3] = 255;
 	}
 
 	//find highest value
 
-	bool use_self = display_time->get_selected() == DISPLAY_SELF_TIME;
+	const bool use_self = display_time->get_selected() == DISPLAY_SELF_TIME;
 	float highest = 0;
 
 	for (int i = 0; i < frame_metrics.size(); i++) {
@@ -319,21 +320,23 @@ void EditorProfiler::_update_plot() {
 
 			for (int j = 0; j < h * 4; j += 4) {
 
-				int a = column[j + 3];
+				const int a = column[j + 3];
 				if (a > 0) {
 					column[j + 0] /= a;
 					column[j + 1] /= a;
 					column[j + 2] /= a;
 				}
 
-				uint8_t r = uint8_t(column[j + 0]);
-				uint8_t g = uint8_t(column[j + 1]);
-				uint8_t b = uint8_t(column[j + 2]);
+				const uint8_t red = uint8_t(column[j + 0]);
+				const uint8_t green = uint8_t(column[j + 1]);
+				const uint8_t blue = uint8_t(column[j + 2]);
+				const bool is_filled = red >= 1 || green >= 1 || blue >= 1;
+				const int widx = ((j >> 2) * w + i) * 4;
 
-				int widx = ((j >> 2) * w + i) * 4;
-				wr[widx + 0] = r;
-				wr[widx + 1] = g;
-				wr[widx + 2] = b;
+				// If the pixel isn't filled by any profiler line, apply the background color instead.
+				wr[widx + 0] = is_filled ? red : Math::fast_ftoi(background_color.r * 255);
+				wr[widx + 1] = is_filled ? green : Math::fast_ftoi(background_color.g * 255);
+				wr[widx + 2] = is_filled ? blue : Math::fast_ftoi(background_color.b * 255);
 				wr[widx + 3] = 255;
 			}
 		}
@@ -729,7 +732,7 @@ EditorProfiler::EditorProfiler() {
 	h_split->set_v_size_flags(SIZE_EXPAND_FILL);
 
 	variables = memnew(Tree);
-	variables->set_custom_minimum_size(Size2(300, 0) * EDSCALE);
+	variables->set_custom_minimum_size(Size2(320, 0) * EDSCALE);
 	variables->set_hide_folding(true);
 	h_split->add_child(variables);
 	variables->set_hide_root(true);
@@ -737,10 +740,10 @@ EditorProfiler::EditorProfiler() {
 	variables->set_column_titles_visible(true);
 	variables->set_column_title(0, TTR("Name"));
 	variables->set_column_expand(0, true);
-	variables->set_column_min_width(0, 60);
+	variables->set_column_min_width(0, 60 * EDSCALE);
 	variables->set_column_title(1, TTR("Time"));
 	variables->set_column_expand(1, false);
-	variables->set_column_min_width(1, 60 * EDSCALE);
+	variables->set_column_min_width(1, 100 * EDSCALE);
 	variables->set_column_title(2, TTR("Calls"));
 	variables->set_column_expand(2, false);
 	variables->set_column_min_width(2, 60 * EDSCALE);
@@ -749,7 +752,6 @@ EditorProfiler::EditorProfiler() {
 	graph = memnew(TextureRect);
 	graph->set_expand(true);
 	graph->set_mouse_filter(MOUSE_FILTER_STOP);
-	//graph->set_ignore_mouse(false);
 	graph->connect("draw", this, "_graph_tex_draw");
 	graph->connect("gui_input", this, "_graph_tex_input");
 	graph->connect("mouse_exited", this, "_graph_tex_mouse_exit");
@@ -760,13 +762,10 @@ EditorProfiler::EditorProfiler() {
 	int metric_size = CLAMP(int(EDITOR_DEF("debugger/profiler_frame_history_size", 600)), 60, 1024);
 	frame_metrics.resize(metric_size);
 	last_metric = -1;
-	//cursor_metric=-1;
 	hover_metric = -1;
 
 	EDITOR_DEF("debugger/profiler_frame_max_functions", 64);
 
-	//display_mode=DISPLAY_FRAME_TIME;
-
 	frame_delay = memnew(Timer);
 	frame_delay->set_wait_time(0.1);
 	frame_delay->set_one_shot(true);
@@ -784,6 +783,4 @@ EditorProfiler::EditorProfiler() {
 
 	seeking = false;
 	graph_height = 1;
-
-	//activate->set_disabled(true);
 }

+ 1 - 0
editor/inspector_dock.cpp

@@ -584,6 +584,7 @@ InspectorDock::InspectorDock(EditorNode *p_editor, EditorData &p_editor_data) {
 	add_child(warning);
 	warning->set_text(TTR("Changes may be lost!"));
 	warning->set_icon(get_icon("NodeWarning", "EditorIcons"));
+	warning->set_clip_text(true);
 	warning->hide();
 	warning->connect("pressed", this, "_warning_pressed");
 

+ 3 - 3
editor/plugins/script_editor_plugin.cpp

@@ -3209,7 +3209,7 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) {
 
 	script_list = memnew(ItemList);
 	scripts_vbox->add_child(script_list);
-	script_list->set_custom_minimum_size(Size2(150, 90) * EDSCALE); //need to give a bit of limit to avoid it from disappearing
+	script_list->set_custom_minimum_size(Size2(150, 60) * EDSCALE); //need to give a bit of limit to avoid it from disappearing
 	script_list->set_v_size_flags(SIZE_EXPAND_FILL);
 	script_split->set_split_offset(140);
 	_sort_list_on_update = true;
@@ -3254,14 +3254,14 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) {
 	overview_vbox->add_child(members_overview);
 
 	members_overview->set_allow_reselect(true);
-	members_overview->set_custom_minimum_size(Size2(0, 90) * EDSCALE); //need to give a bit of limit to avoid it from disappearing
+	members_overview->set_custom_minimum_size(Size2(0, 60) * EDSCALE); //need to give a bit of limit to avoid it from disappearing
 	members_overview->set_v_size_flags(SIZE_EXPAND_FILL);
 	members_overview->set_allow_rmb_select(true);
 
 	help_overview = memnew(ItemList);
 	overview_vbox->add_child(help_overview);
 	help_overview->set_allow_reselect(true);
-	help_overview->set_custom_minimum_size(Size2(0, 90) * EDSCALE); //need to give a bit of limit to avoid it from disappearing
+	help_overview->set_custom_minimum_size(Size2(0, 60) * EDSCALE); //need to give a bit of limit to avoid it from disappearing
 	help_overview->set_v_size_flags(SIZE_EXPAND_FILL);
 
 	tab_container = memnew(TabContainer);

+ 1 - 0
editor/project_manager.cpp

@@ -1316,6 +1316,7 @@ void ProjectList::create_project_item_control(int p_index) {
 	// The project icon may not be loaded by the time the control is displayed,
 	// so use a loading placeholder.
 	tf->set_texture(get_icon("ProjectIconLoading", "EditorIcons"));
+	tf->set_v_size_flags(SIZE_SHRINK_CENTER);
 	if (item.missing) {
 		tf->set_modulate(Color(1, 1, 1, 0.5));
 	}

+ 1 - 1
editor/script_create_dialog.cpp

@@ -644,7 +644,7 @@ void ScriptCreateDialog::_update_dialog() {
 	}
 
 	if (script_ok) {
-		_msg_script_valid(true, TTR("Script is valid."));
+		_msg_script_valid(true, TTR("Script path/name is valid."));
 	}
 
 	// Does script have named classes?

+ 11 - 10
editor/script_editor_debugger.cpp

@@ -806,25 +806,25 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
 			p.write[i] = arr[i];
 			if (i < perf_items.size()) {
 
-				float v = p[i];
-				String vs = rtos(v);
-				String tt = vs;
+				const float value = p[i];
+				String label = rtos(value);
+				String tooltip = label;
 				switch (Performance::MonitorType((int)perf_items[i]->get_metadata(1))) {
 					case Performance::MONITOR_TYPE_MEMORY: {
-						vs = String::humanize_size(v);
-						tt = vs;
+						label = String::humanize_size(value);
+						tooltip = label;
 					} break;
 					case Performance::MONITOR_TYPE_TIME: {
-						tt += " seconds";
-						vs += " s";
+						label = rtos(value * 1000).pad_decimals(2) + " ms";
+						tooltip = label;
 					} break;
 					default: {
-						tt += " " + perf_items[i]->get_text(0);
+						tooltip += " " + perf_items[i]->get_text(0);
 					} break;
 				}
 
-				perf_items[i]->set_text(1, vs);
-				perf_items[i]->set_tooltip(1, tt);
+				perf_items[i]->set_text(1, label);
+				perf_items[i]->set_tooltip(1, tooltip);
 				if (p[i] > perf_max[i])
 					perf_max.write[i] = p[i];
 			}
@@ -1622,6 +1622,7 @@ void ScriptEditorDebugger::_output_clear() {
 void ScriptEditorDebugger::_export_csv() {
 
 	file_dialog->set_mode(EditorFileDialog::MODE_SAVE_FILE);
+	file_dialog->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
 	file_dialog_mode = SAVE_CSV;
 	file_dialog->popup_centered_ratio();
 }

+ 1 - 1
modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/NodeExtensions.cs

@@ -9,7 +9,7 @@ namespace Godot
 
         public T GetNodeOrNull<T>(NodePath path) where T : class
         {
-            return GetNode(path) as T;
+            return GetNodeOrNull(path) as T;
         }
 
         public T GetChild<T>(int idx) where T : class

+ 2 - 1
modules/opensimplex/doc_classes/OpenSimplexNoise.xml

@@ -117,7 +117,8 @@
 			Difference in period between [member octaves].
 		</member>
 		<member name="octaves" type="int" setter="set_octaves" getter="get_octaves" default="3">
-			Number of OpenSimplex noise layers that are sampled to get the fractal noise.
+			Number of OpenSimplex noise layers that are sampled to get the fractal noise. Higher values result in more detailed noise but take more time to generate.
+			[b]Note:[/b] The maximum allowed value is 9.
 		</member>
 		<member name="period" type="float" setter="set_period" getter="get_period" default="64.0">
 			Period of the base octave. A lower period results in a higher-frequency noise (more value changes across the same distance).

+ 6 - 3
modules/opensimplex/open_simplex_noise.cpp

@@ -47,7 +47,7 @@ OpenSimplexNoise::~OpenSimplexNoise() {
 }
 
 void OpenSimplexNoise::_init_seeds() {
-	for (int i = 0; i < 6; ++i) {
+	for (int i = 0; i < MAX_OCTAVES; ++i) {
 		open_simplex_noise(seed + i * 2, &(contexts[i]));
 	}
 }
@@ -71,7 +71,10 @@ int OpenSimplexNoise::get_seed() {
 
 void OpenSimplexNoise::set_octaves(int p_octaves) {
 	if (p_octaves == octaves) return;
-	octaves = CLAMP(p_octaves, 1, 6);
+
+	ERR_FAIL_COND_MSG(p_octaves > MAX_OCTAVES, vformat("The number of OpenSimplexNoise octaves is limited to %d; ignoring the new value.", MAX_OCTAVES));
+
+	octaves = CLAMP(p_octaves, 1, MAX_OCTAVES);
 	emit_changed();
 }
 
@@ -182,7 +185,7 @@ void OpenSimplexNoise::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("get_noise_3dv", "pos"), &OpenSimplexNoise::get_noise_3dv);
 
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "seed"), "set_seed", "get_seed");
-	ADD_PROPERTY(PropertyInfo(Variant::INT, "octaves", PROPERTY_HINT_RANGE, "1,6,1"), "set_octaves", "get_octaves");
+	ADD_PROPERTY(PropertyInfo(Variant::INT, "octaves", PROPERTY_HINT_RANGE, vformat("1,%d,1", MAX_OCTAVES)), "set_octaves", "get_octaves");
 	ADD_PROPERTY(PropertyInfo(Variant::REAL, "period", PROPERTY_HINT_RANGE, "0.1,256.0,0.1"), "set_period", "get_period");
 	ADD_PROPERTY(PropertyInfo(Variant::REAL, "persistence", PROPERTY_HINT_RANGE, "0.0,1.0,0.001"), "set_persistence", "get_persistence");
 	ADD_PROPERTY(PropertyInfo(Variant::REAL, "lacunarity", PROPERTY_HINT_RANGE, "0.1,4.0,0.01"), "set_lacunarity", "get_lacunarity");

+ 6 - 1
modules/opensimplex/open_simplex_noise.h

@@ -37,11 +37,16 @@
 
 #include "thirdparty/misc/open-simplex-noise.h"
 
+// The maximum number of octaves allowed. Note that these are statically allocated.
+// Higher values become exponentially slower, so this shouldn't be set too high
+// to avoid freezing the editor for long periods of time.
+#define MAX_OCTAVES 9
+
 class OpenSimplexNoise : public Resource {
 	GDCLASS(OpenSimplexNoise, Resource);
 	OBJ_SAVE_TYPE(OpenSimplexNoise);
 
-	osn_context contexts[6];
+	osn_context contexts[MAX_OCTAVES];
 
 	int seed;
 	float persistence; // Controls details, value in [0,1]. Higher increases grain, lower increases smoothness.

+ 1 - 1
modules/stb_vorbis/audio_stream_ogg_vorbis.cpp

@@ -57,7 +57,7 @@ void AudioStreamPlaybackOGGVorbis::_mix_internal(AudioFrame *p_buffer, int p_fra
 
 		if (todo) {
 			//end of file!
-			if (vorbis_stream->loop) {
+			if (vorbis_stream->loop && mixed > 0) {
 				//loop
 				seek(vorbis_stream->loop_offset);
 				loops++;

+ 5 - 8
platform/android/export/export.cpp

@@ -642,9 +642,6 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
 		String dst_path = p_path.replace_first("res://", "assets/");
 
 		store_in_apk(ed, dst_path, p_data, _should_compress_asset(p_path, p_data) ? Z_DEFLATED : 0);
-		if (ed->ep->step("File: " + p_path, 3 + p_file * 100 / p_total)) {
-			return ERR_SKIP;
-		}
 		return OK;
 	}
 
@@ -1497,7 +1494,7 @@ public:
 		String adb = EditorSettings::get_singleton()->get("export/android/adb");
 
 		// Export_temp APK.
-		if (ep.step("Exporting APK", 0)) {
+		if (ep.step("Exporting APK...", 0)) {
 			device_lock->unlock();
 			return ERR_SKIP;
 		}
@@ -1547,7 +1544,7 @@ public:
 		}
 
 		print_line("Installing to device (please wait...): " + devices[p_device].name);
-		if (ep.step("Installing to device (please wait...)", 2)) {
+		if (ep.step("Installing to device, please wait...", 2)) {
 			CLEANUP_AND_RETURN(ERR_SKIP);
 		}
 
@@ -1614,7 +1611,7 @@ public:
 			}
 		}
 
-		if (ep.step("Running on Device...", 3)) {
+		if (ep.step("Running on device...", 3)) {
 			CLEANUP_AND_RETURN(ERR_SKIP);
 		}
 		args.clear();
@@ -2119,7 +2116,7 @@ public:
 		FileAccess *src_f = NULL;
 		zlib_filefunc_def io = zipio_create_io_from_file(&src_f);
 
-		if (ep.step("Creating APK", 0)) {
+		if (ep.step("Creating APK...", 0)) {
 			return ERR_SKIP;
 		}
 
@@ -2281,7 +2278,7 @@ public:
 			ret = unzGoToNextFile(pkg);
 		}
 
-		if (ep.step("Adding Files...", 1)) {
+		if (ep.step("Adding files...", 1)) {
 			CLEANUP_AND_RETURN(ERR_SKIP);
 		}
 		Error err = OK;

+ 1 - 1
platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java

@@ -123,7 +123,7 @@ public class GodotEditText extends EditText {
 	}
 
 	private void setMaxInputLength(EditText p_edit_text, int p_max_input_length) {
-		if (p_max_input_length >= 0) {
+		if (p_max_input_length > 0) {
 			InputFilter[] filters = new InputFilter[1];
 			filters[0] = new InputFilter.LengthFilter(p_max_input_length);
 			p_edit_text.setFilters(filters);

+ 5 - 0
platform/javascript/detect.py

@@ -131,6 +131,11 @@ def configure(env):
 
     env.Append(LINKFLAGS=['-s', 'BINARYEN=1'])
 
+    # Only include the JavaScript support code for the web environment
+    # (i.e. exclude Node.js and other unused environments).
+    # This makes the JavaScript support code about 4 KB smaller.
+    env.Append(LINKFLAGS=['-s', 'ENVIRONMENT=web'])
+
     # This needs to be defined for Emscripten using 'fastcomp' (default pre-1.39.0)
     # and undefined if using 'upstream'. And to make things simple, earlier
     # Emscripten versions didn't include 'fastcomp' in their path, so we check

+ 18 - 0
platform/osx/detect.py

@@ -27,6 +27,9 @@ def get_opts():
         ('MACOS_SDK_PATH', 'Path to the macOS SDK', ''),
         EnumVariable('debug_symbols', 'Add debugging symbols to release builds', 'yes', ('yes', 'no', 'full')),
         BoolVariable('separate_debug_symbols', 'Create a separate file containing debugging symbols', False),
+        BoolVariable('use_ubsan', 'Use LLVM/GCC compiler undefined behavior sanitizer (UBSAN)', False),
+        BoolVariable('use_asan', 'Use LLVM/GCC compiler address sanitizer (ASAN))', False),
+        BoolVariable('use_tsan', 'Use LLVM/GCC compiler thread sanitizer (TSAN))', False),
     ]
 
 
@@ -122,6 +125,21 @@ def configure(env):
         env["CC"] = "clang"
         env["LINK"] = "clang++"
 
+    if env['use_ubsan'] or env['use_asan'] or env['use_tsan']:
+        env.extra_suffix += "s"
+
+        if env['use_ubsan']:
+            env.Append(CCFLAGS=['-fsanitize=undefined'])
+            env.Append(LINKFLAGS=['-fsanitize=undefined'])
+
+        if env['use_asan']:
+            env.Append(CCFLAGS=['-fsanitize=address'])
+            env.Append(LINKFLAGS=['-fsanitize=address'])
+
+        if env['use_tsan']:
+            env.Append(CCFLAGS=['-fsanitize=thread'])
+            env.Append(LINKFLAGS=['-fsanitize=thread'])
+
     ## Dependencies
 
     if env['builtin_libtheora']:

+ 20 - 6
platform/osx/os_osx.mm

@@ -115,6 +115,20 @@ static Vector2 get_mouse_pos(NSPoint locationInWindow, CGFloat backingScaleFacto
 	return Vector2(mouse_x, mouse_y);
 }
 
+static NSCursor *cursorFromSelector(SEL selector, SEL fallback = nil) {
+	if ([NSCursor respondsToSelector:selector]) {
+		id object = [NSCursor performSelector:selector];
+		if ([object isKindOfClass:[NSCursor class]]) {
+			return object;
+		}
+	}
+	if (fallback) {
+		// Fallback should be a reasonable default, no need to check.
+		return [NSCursor performSelector:fallback];
+	}
+	return [NSCursor arrowCursor];
+}
+
 @interface GodotApplication : NSApplication
 @end
 
@@ -1813,15 +1827,15 @@ void OS_OSX::set_cursor_shape(CursorShape p_shape) {
 			case CURSOR_BUSY: [[NSCursor arrowCursor] set]; break;
 			case CURSOR_DRAG: [[NSCursor closedHandCursor] set]; break;
 			case CURSOR_CAN_DROP: [[NSCursor openHandCursor] set]; break;
-			case CURSOR_FORBIDDEN: [[NSCursor arrowCursor] set]; break;
-			case CURSOR_VSIZE: [[NSCursor resizeUpDownCursor] set]; break;
-			case CURSOR_HSIZE: [[NSCursor resizeLeftRightCursor] set]; break;
-			case CURSOR_BDIAGSIZE: [[NSCursor arrowCursor] set]; break;
-			case CURSOR_FDIAGSIZE: [[NSCursor arrowCursor] set]; break;
+			case CURSOR_FORBIDDEN: [[NSCursor operationNotAllowedCursor] set]; break;
+			case CURSOR_VSIZE: [cursorFromSelector(@selector(_windowResizeNorthSouthCursor), @selector(resizeUpDownCursor)) set]; break;
+			case CURSOR_HSIZE: [cursorFromSelector(@selector(_windowResizeEastWestCursor), @selector(resizeLeftRightCursor)) set]; break;
+			case CURSOR_BDIAGSIZE: [cursorFromSelector(@selector(_windowResizeNorthEastSouthWestCursor)) set]; break;
+			case CURSOR_FDIAGSIZE: [cursorFromSelector(@selector(_windowResizeNorthWestSouthEastCursor)) set]; break;
 			case CURSOR_MOVE: [[NSCursor arrowCursor] set]; break;
 			case CURSOR_VSPLIT: [[NSCursor resizeUpDownCursor] set]; break;
 			case CURSOR_HSPLIT: [[NSCursor resizeLeftRightCursor] set]; break;
-			case CURSOR_HELP: [[NSCursor arrowCursor] set]; break;
+			case CURSOR_HELP: [cursorFromSelector(@selector(_helpCursor)) set]; break;
 			default: {
 			};
 		}

+ 1 - 1
platform/uwp/export/export.cpp

@@ -1176,7 +1176,7 @@ public:
 			err += TTR("Invalid square 71x71 logo image dimensions (should be 71x71).") + "\n";
 		}
 
-		if (!p_preset->get("images/square150x150_logo").is_zero() && !_valid_image((Object::cast_to<StreamTexture>((Object *)p_preset->get("images/square150x150_logo"))), 150, 0)) {
+		if (!p_preset->get("images/square150x150_logo").is_zero() && !_valid_image((Object::cast_to<StreamTexture>((Object *)p_preset->get("images/square150x150_logo"))), 150, 150)) {
 			valid = false;
 			err += TTR("Invalid square 150x150 logo image dimensions (should be 150x150).") + "\n";
 		}

+ 7 - 2
platform/x11/os_x11.cpp

@@ -1429,11 +1429,15 @@ void OS_X11::set_window_fullscreen(bool p_enabled) {
 		set_window_maximized(true);
 	}
 	set_wm_fullscreen(p_enabled);
-	if (!p_enabled && !current_videomode.always_on_top) {
+	if (!p_enabled && current_videomode.always_on_top) {
 		// Restore
 		set_window_maximized(false);
 	}
-
+	if (!p_enabled) {
+		set_window_position(last_position_before_fs);
+	} else {
+		last_position_before_fs = get_window_position();
+	}
 	current_videomode.fullscreen = p_enabled;
 }
 
@@ -3502,4 +3506,5 @@ OS_X11::OS_X11() {
 	window_focused = true;
 	xim_style = 0L;
 	mouse_mode = MOUSE_MODE_VISIBLE;
+	last_position_before_fs = Vector2();
 }

+ 1 - 0
platform/x11/os_x11.h

@@ -115,6 +115,7 @@ class OS_X11 : public OS_Unix {
 	// IME
 	bool im_active;
 	Vector2 im_position;
+	Vector2 last_position_before_fs;
 
 	Size2 min_size;
 	Size2 max_size;

+ 8 - 2
scene/2d/path_2d.cpp

@@ -120,9 +120,15 @@ void Path2D::_notification(int p_what) {
 }
 
 void Path2D::_curve_changed() {
+	if (!is_inside_tree()) {
+		return;
+	}
+
+	if (!Engine::get_singleton()->is_editor_hint() && !get_tree()->is_debugging_navigation_hint()) {
+		return;
+	}
 
-	if (is_inside_tree() && Engine::get_singleton()->is_editor_hint())
-		update();
+	update();
 }
 
 void Path2D::set_curve(const Ref<Curve2D> &p_curve) {

+ 0 - 5
scene/gui/control.cpp

@@ -462,11 +462,6 @@ void Control::_update_canvas_item_transform() {
 	Transform2D xform = _get_internal_transform();
 	xform[2] += get_position();
 
-	// We use a little workaround to avoid flickering when moving the pivot with _edit_set_pivot()
-	if (is_inside_tree() && Math::abs(Math::sin(data.rotation * 4.0f)) < 0.00001f && get_viewport()->is_snap_controls_to_pixels_enabled()) {
-		xform[2] = xform[2].round();
-	}
-
 	VisualServer::get_singleton()->canvas_item_set_transform(get_canvas_item(), xform);
 }
 

+ 8 - 1
scene/gui/option_button.cpp

@@ -36,7 +36,14 @@ Size2 OptionButton::get_minimum_size() const {
 	Size2 minsize = Button::get_minimum_size();
 
 	if (has_icon("arrow")) {
-		minsize.width += Control::get_icon("arrow")->get_width() + get_constant("hseparation");
+		const Size2 padding = get_stylebox("normal")->get_minimum_size();
+		const Size2 arrow_size = Control::get_icon("arrow")->get_size();
+
+		Size2 content_size = minsize - padding;
+		content_size.width += arrow_size.width + get_constant("hseparation");
+		content_size.height = MAX(content_size.height, arrow_size.height);
+
+		minsize = content_size + padding;
 	}
 
 	return minsize;

+ 18 - 18
scene/resources/tile_set.cpp

@@ -325,14 +325,14 @@ void TileSet::_get_property_list(List<PropertyInfo> *p_list) const {
 
 		int id = E->key();
 		String pre = itos(id) + "/";
-		p_list->push_back(PropertyInfo(Variant::STRING, pre + "name"));
-		p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"));
-		p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "normal_map", PROPERTY_HINT_RESOURCE_TYPE, "Texture"));
-		p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "tex_offset"));
-		p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial"));
-		p_list->push_back(PropertyInfo(Variant::COLOR, pre + "modulate"));
-		p_list->push_back(PropertyInfo(Variant::RECT2, pre + "region"));
-		p_list->push_back(PropertyInfo(Variant::INT, pre + "tile_mode", PROPERTY_HINT_ENUM, "SINGLE_TILE,AUTO_TILE,ATLAS_TILE"));
+		p_list->push_back(PropertyInfo(Variant::STRING, pre + "name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
+		p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture", PROPERTY_USAGE_NOEDITOR));
+		p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "normal_map", PROPERTY_HINT_RESOURCE_TYPE, "Texture", PROPERTY_USAGE_NOEDITOR));
+		p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "tex_offset", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
+		p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial", PROPERTY_USAGE_NOEDITOR));
+		p_list->push_back(PropertyInfo(Variant::COLOR, pre + "modulate", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
+		p_list->push_back(PropertyInfo(Variant::RECT2, pre + "region", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
+		p_list->push_back(PropertyInfo(Variant::INT, pre + "tile_mode", PROPERTY_HINT_ENUM, "SINGLE_TILE,AUTO_TILE,ATLAS_TILE", PROPERTY_USAGE_NOEDITOR));
 		if (tile_get_tile_mode(id) == AUTO_TILE) {
 			p_list->push_back(PropertyInfo(Variant::INT, pre + "autotile/bitmask_mode", PROPERTY_HINT_ENUM, "2X2,3X3 (minimal),3X3", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
 			p_list->push_back(PropertyInfo(Variant::ARRAY, pre + "autotile/bitmask_flags", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
@@ -352,17 +352,17 @@ void TileSet::_get_property_list(List<PropertyInfo> *p_list) const {
 			p_list->push_back(PropertyInfo(Variant::ARRAY, pre + "autotile/priority_map", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
 			p_list->push_back(PropertyInfo(Variant::ARRAY, pre + "autotile/z_index_map", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
 		}
-		p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "occluder_offset"));
-		p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "occluder", PROPERTY_HINT_RESOURCE_TYPE, "OccluderPolygon2D"));
-		p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "navigation_offset"));
-		p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "navigation", PROPERTY_HINT_RESOURCE_TYPE, "NavigationPolygon"));
-		p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "shape_offset", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR));
-		p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "shape_transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR));
-		p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape2D", PROPERTY_USAGE_EDITOR));
-		p_list->push_back(PropertyInfo(Variant::BOOL, pre + "shape_one_way", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR));
-		p_list->push_back(PropertyInfo(Variant::REAL, pre + "shape_one_way_margin", PROPERTY_HINT_RANGE, "0,128,0.01", PROPERTY_USAGE_EDITOR));
+		p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "occluder_offset", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
+		p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "occluder", PROPERTY_HINT_RESOURCE_TYPE, "OccluderPolygon2D", PROPERTY_USAGE_NOEDITOR));
+		p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "navigation_offset", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
+		p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "navigation", PROPERTY_HINT_RESOURCE_TYPE, "NavigationPolygon", PROPERTY_USAGE_NOEDITOR));
+		p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "shape_offset", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
+		p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "shape_transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
+		p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape2D", PROPERTY_USAGE_NOEDITOR));
+		p_list->push_back(PropertyInfo(Variant::BOOL, pre + "shape_one_way", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
+		p_list->push_back(PropertyInfo(Variant::REAL, pre + "shape_one_way_margin", PROPERTY_HINT_RANGE, "0,128,0.01", PROPERTY_USAGE_NOEDITOR));
 		p_list->push_back(PropertyInfo(Variant::ARRAY, pre + "shapes", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
-		p_list->push_back(PropertyInfo(Variant::INT, pre + "z_index", PROPERTY_HINT_RANGE, itos(VS::CANVAS_ITEM_Z_MIN) + "," + itos(VS::CANVAS_ITEM_Z_MAX) + ",1"));
+		p_list->push_back(PropertyInfo(Variant::INT, pre + "z_index", PROPERTY_HINT_RANGE, itos(VS::CANVAS_ITEM_Z_MIN) + "," + itos(VS::CANVAS_ITEM_Z_MAX) + ",1", PROPERTY_USAGE_NOEDITOR));
 	}
 }
 

+ 1 - 1
scene/resources/visual_shader.cpp

@@ -1890,7 +1890,7 @@ const VisualShaderNodeOutput::Port VisualShaderNodeOutput::ports[] = {
 	{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "normalmap_depth", "NORMALMAP_DEPTH" },
 	// Canvas Item, Light
 	{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "light", "LIGHT.rgb" },
-	{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "light_alpha", "LIGHT.rgb" },
+	{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "light_alpha", "LIGHT.a" },
 	// Particles, Vertex
 	{ Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" },
 	{ Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" },

+ 2 - 0
servers/visual/shader_language.cpp

@@ -662,6 +662,8 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
 						idx++;
 					}
 
+					str = str.replace("dus_", "_");
+
 					return _make_token(TK_IDENTIFIER, str);
 				}