summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CONTRIBUTING.md18
-rw-r--r--core/class_db.cpp3
-rw-r--r--core/math/math_defs.h4
-rw-r--r--core/os/file_access.cpp2
-rw-r--r--core/script_debugger_remote.cpp2
-rw-r--r--core/undo_redo.cpp7
-rw-r--r--core/undo_redo.h2
-rw-r--r--doc/Doxyfile126
-rw-r--r--doc/classes/ARVRInterface.xml4
-rw-r--r--doc/classes/Animation.xml2
-rw-r--r--doc/classes/AudioEffectReverb.xml2
-rw-r--r--doc/classes/BaseButton.xml3
-rw-r--r--doc/classes/Dictionary.xml22
-rw-r--r--doc/classes/DynamicFontData.xml3
-rw-r--r--doc/classes/Environment.xml3
-rw-r--r--doc/classes/File.xml2
-rw-r--r--doc/classes/Generic6DOFJoint.xml78
-rw-r--r--doc/classes/Object.xml10
-rw-r--r--doc/classes/OrientedPathFollow.xml2
-rw-r--r--doc/classes/PHashTranslation.xml1
-rw-r--r--doc/classes/PhysicsServer.xml22
-rw-r--r--doc/classes/SpatialMaterial.xml4
-rw-r--r--doc/classes/StyleBoxFlat.xml33
-rw-r--r--doc/classes/Translation.xml12
-rw-r--r--doc/classes/TranslationServer.xml12
-rw-r--r--doc/classes/Tree.xml6
-rw-r--r--doc/classes/UndoRedo.xml3
-rw-r--r--doc/classes/Viewport.xml14
-rw-r--r--doc/classes/VisualServer.xml8
-rw-r--r--drivers/gles2/shader_compiler_gles2.cpp9
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp11
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.cpp11
-rw-r--r--drivers/gles3/shader_compiler_gles3.cpp14
-rw-r--r--drivers/gles3/shaders/scene.glsl20
-rw-r--r--editor/array_property_edit.cpp11
-rw-r--r--editor/code_editor.cpp33
-rw-r--r--editor/code_editor.h7
-rw-r--r--editor/editor_file_system.cpp33
-rw-r--r--editor/editor_file_system.h3
-rw-r--r--editor/editor_fonts.cpp16
-rw-r--r--editor/editor_help.cpp478
-rw-r--r--editor/editor_help.h89
-rw-r--r--editor/editor_help_search.cpp597
-rw-r--r--editor/editor_help_search.h156
-rw-r--r--editor/editor_node.cpp104
-rw-r--r--editor/editor_node.h4
-rw-r--r--editor/editor_properties.cpp32
-rw-r--r--editor/editor_properties.h9
-rw-r--r--editor/editor_properties_array_dict.cpp54
-rw-r--r--editor/editor_properties_array_dict.h3
-rw-r--r--editor/editor_settings.cpp2
-rw-r--r--editor/import/editor_import_collada.cpp2
-rw-r--r--editor/import/editor_scene_importer_gltf.cpp13
-rw-r--r--editor/import/resource_importer_texture.cpp2
-rw-r--r--editor/plugins/animation_blend_space_2d_editor.cpp15
-rw-r--r--editor/plugins/animation_blend_space_2d_editor.h1
-rw-r--r--editor/plugins/script_editor_plugin.cpp33
-rw-r--r--editor/plugins/script_editor_plugin.h5
-rw-r--r--editor/plugins/script_text_editor.cpp3
-rw-r--r--editor/plugins/shader_editor_plugin.cpp1
-rw-r--r--editor/plugins/spatial_editor_plugin.cpp12
-rw-r--r--editor/plugins/spatial_editor_plugin.h6
-rw-r--r--editor/script_editor_debugger.cpp1
-rw-r--r--gles_builders.py4
-rw-r--r--methods.py26
-rw-r--r--modules/bullet/rigid_body_bullet.cpp21
-rw-r--r--modules/bullet/rigid_body_bullet.h15
-rw-r--r--modules/bullet/space_bullet.cpp10
-rw-r--r--modules/csg/csg_shape.cpp51
-rw-r--r--modules/gdnative/gdnative_builders.py24
-rw-r--r--modules/gdscript/gdscript.cpp45
-rw-r--r--modules/mono/glue/Managed/Files/AABB.cs4
-rw-r--r--modules/mono/glue/Managed/Files/Basis.cs45
-rw-r--r--modules/mono/glue/Managed/Files/Color.cs4
-rw-r--r--modules/mono/glue/Managed/Files/Mathf.cs4
-rw-r--r--modules/mono/glue/Managed/Files/MathfEx.cs2
-rw-r--r--modules/mono/glue/Managed/Files/Plane.cs6
-rw-r--r--modules/mono/glue/Managed/Files/Quat.cs2
-rw-r--r--modules/mono/glue/Managed/Files/Rect2.cs4
-rw-r--r--modules/mono/glue/Managed/Files/StringExtensions.cs8
-rw-r--r--modules/mono/glue/Managed/Files/Transform.cs8
-rw-r--r--modules/mono/glue/Managed/Files/Transform2D.cs6
-rw-r--r--modules/mono/glue/Managed/Files/Vector2.cs4
-rw-r--r--modules/mono/glue/Managed/Files/Vector3.cs12
-rw-r--r--modules/mono/glue/Managed/Properties/AssemblyInfo.cs4
-rw-r--r--modules/visual_script/doc_classes/VisualScriptCustomNode.xml2
-rw-r--r--modules/visual_script/visual_script_editor.cpp2
-rw-r--r--modules/visual_script/visual_script_editor.h2
-rw-r--r--platform/android/detect.py6
-rw-r--r--platform/android/java/res/layout/status_bar_ongoing_event_progress_bar.xml4
-rw-r--r--platform/android/java/src/org/godotengine/godot/utils/CustomSSLSocketFactory.java2
-rw-r--r--platform/android/java/src/org/godotengine/godot/utils/HttpRequester.java2
-rw-r--r--platform/android/java/src/org/godotengine/godot/utils/RequestParams.java2
-rw-r--r--platform/android/java_glue.cpp6
-rw-r--r--platform/android/power_android.cpp2
-rw-r--r--platform/iphone/detect.py9
-rw-r--r--platform/iphone/export/export.cpp18
-rw-r--r--platform/osx/detect.py6
-rw-r--r--platform/osx/os_osx.mm21
-rw-r--r--platform/windows/detect.py4
-rw-r--r--platform/x11/os_x11.cpp2
-rw-r--r--scene/2d/physics_body_2d.cpp4
-rw-r--r--scene/2d/visibility_notifier_2d.cpp2
-rw-r--r--scene/3d/physics_body.cpp72
-rw-r--r--scene/3d/physics_body.h18
-rw-r--r--scene/3d/physics_joint.cpp1
-rw-r--r--scene/3d/sprite_3d.cpp16
-rw-r--r--scene/3d/visibility_notifier.cpp2
-rw-r--r--scene/animation/animation_blend_space_2d.cpp185
-rw-r--r--scene/animation/animation_blend_space_2d.h15
-rw-r--r--scene/animation/animation_blend_tree.cpp2
-rw-r--r--scene/animation/skeleton_ik.cpp22
-rw-r--r--scene/animation/skeleton_ik.h6
-rw-r--r--scene/gui/base_button.cpp16
-rw-r--r--scene/gui/base_button.h4
-rw-r--r--scene/gui/split_container.cpp50
-rw-r--r--scene/gui/split_container.h4
-rw-r--r--scene/gui/tree.cpp2
-rw-r--r--scene/main/node.cpp80
-rw-r--r--scene/resources/dynamic_font.cpp18
-rw-r--r--scene/resources/dynamic_font.h3
-rw-r--r--scene/resources/material.cpp4
-rw-r--r--scene/resources/primitive_meshes.cpp44
-rw-r--r--servers/audio/audio_rb_resampler.cpp32
-rw-r--r--servers/visual/shader_language.cpp5
-rw-r--r--servers/visual/shader_language.h2
-rw-r--r--servers/visual/visual_server_canvas.cpp22
-rw-r--r--thirdparty/enet/godot.cpp64
128 files changed, 2071 insertions, 1223 deletions
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index a8e4650710..04e42d14b6 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -59,7 +59,8 @@ by drag and dropping the file in the GitHub edition field.
If you want to add new engine functionalities, please make sure that:
-* This functionality is desired.
+* This functionality is desired, which means that it solves a common use case
+ that several users will need in their real-life projects.
* You talked to other developers on how to implement it best (on either
communication channel, and maybe in a GitHub issue first before making your
PR).
@@ -70,10 +71,18 @@ Similar rules can be applied when contributing bug fixes - it's always best to
discuss the implementation in the bug report first if you are not 100% about
what would be the best fix.
+[This blog post](https://godotengine.org/article/will-your-contribution-be-merged-heres-how-tell)
+outlines the process used by core developers when assessing PRs. We strongly
+recommend that you have a look at it to know what's important to take into
+account for a PR to be considered for merging.
+
In addition to the following tips, also take a look at the
[Engine development guide](https://docs.godotengine.org/en/latest/development/cpp/)
for an introduction to developing on Godot.
+The [Contributing docs](http://docs.godotengine.org/en/latest/community/contributing/index.html)
+also have important information on the PR workflow and the code style we use.
+
#### Be nice to the git history
Try to make simple PRs that handle one specific topic. Just like for reporting
@@ -93,6 +102,9 @@ Internet).
This git style guide has some good practices to have in mind:
[Git Style Guide](https://github.com/agis-/git-style-guide)
+See our [PR workflow](http://docs.godotengine.org/en/latest/community/contributing/pr_workflow.html)
+documentation for tips on using Git, amending commits and rebasing branches.
+
#### Format your commit logs with readability in mind
The way you format your commit logs is quite important to ensure that the
@@ -138,6 +150,10 @@ Weblate](https://hosted.weblate.org/projects/godot-engine/godot), an open
source and web-based translation platform. Please refer to the [translation
readme](editor/translations/README.md) for more information.
+You can also help translate [Godot's
+documentation](https://hosted.weblate.org/projects/godot-engine/godot-docs/)
+on Weblate.
+
## Communicating with developers
The Godot Engine community has [many communication
diff --git a/core/class_db.cpp b/core/class_db.cpp
index 6565d242a2..052a4586fe 100644
--- a/core/class_db.cpp
+++ b/core/class_db.cpp
@@ -936,9 +936,8 @@ void ClassDB::add_property(StringName p_class, const PropertyInfo &p_pinfo, cons
}
#ifdef DEBUG_METHODS_ENABLED
-
if (type->property_setget.has(p_pinfo.name)) {
- ERR_EXPLAIN("Object already has property: " + p_class);
+ ERR_EXPLAIN("Object " + p_class + " already has property: " + p_pinfo.name);
ERR_FAIL();
}
#endif
diff --git a/core/math/math_defs.h b/core/math/math_defs.h
index a5feee6eb5..db9055cee2 100644
--- a/core/math/math_defs.h
+++ b/core/math/math_defs.h
@@ -93,9 +93,9 @@ enum Corner {
};
/**
- * The "Real" type is an abstract type used for real numbers, such as 1.5,
+ * The "Real" type is an abstract type used for real numbers, such as 1.5,
* in contrast to integer numbers. Precision can be controlled with the
- * presence or absence of the REAL_T_IS_DOUBLE define.
+ * presence or absence of the REAL_T_IS_DOUBLE define.
*/
#ifdef REAL_T_IS_DOUBLE
typedef double real_t;
diff --git a/core/os/file_access.cpp b/core/os/file_access.cpp
index 8f4fae9eb1..679b1c9054 100644
--- a/core/os/file_access.cpp
+++ b/core/os/file_access.cpp
@@ -534,7 +534,7 @@ void FileAccess::store_csv_line(const Vector<String> &p_values, const String &p_
for (int i = 0; i < size; ++i) {
String value = p_values[i];
- if (value.find("\"") != -1 || value.find(p_delim) != -1 || value.find("\n")) {
+ if (value.find("\"") != -1 || value.find(p_delim) != -1 || value.find("\n") != -1) {
value = "\"" + value.replace("\"", "\"\"") + "\"";
}
if (i < size - 1) {
diff --git a/core/script_debugger_remote.cpp b/core/script_debugger_remote.cpp
index 621a94ab1a..a03ddd0983 100644
--- a/core/script_debugger_remote.cpp
+++ b/core/script_debugger_remote.cpp
@@ -108,7 +108,7 @@ void ScriptDebuggerRemote::_put_variable(const String &p_name, const Variant &p_
}
int len = 0;
- Error err = encode_variant(var, NULL, len);
+ Error err = encode_variant(var, NULL, len, true);
if (err != OK)
ERR_PRINT("Failed to encode variant");
diff --git a/core/undo_redo.cpp b/core/undo_redo.cpp
index 6f7c8ea08a..3d41c374ea 100644
--- a/core/undo_redo.cpp
+++ b/core/undo_redo.cpp
@@ -325,7 +325,7 @@ bool UndoRedo::undo() {
return true;
}
-void UndoRedo::clear_history() {
+void UndoRedo::clear_history(bool p_increase_version) {
ERR_FAIL_COND(action_level > 0);
_discard_redo();
@@ -333,7 +333,8 @@ void UndoRedo::clear_history() {
while (actions.size())
_pop_history_tail();
- version++;
+ if (p_increase_version)
+ version++;
}
String UndoRedo::get_current_action_name() const {
@@ -493,7 +494,7 @@ void UndoRedo::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_undo_property", "object", "property", "value"), &UndoRedo::add_undo_property);
ClassDB::bind_method(D_METHOD("add_do_reference", "object"), &UndoRedo::add_do_reference);
ClassDB::bind_method(D_METHOD("add_undo_reference", "object"), &UndoRedo::add_undo_reference);
- ClassDB::bind_method(D_METHOD("clear_history"), &UndoRedo::clear_history);
+ ClassDB::bind_method(D_METHOD("clear_history", "increase_version"), &UndoRedo::clear_history, DEFVAL(true));
ClassDB::bind_method(D_METHOD("get_current_action_name"), &UndoRedo::get_current_action_name);
ClassDB::bind_method(D_METHOD("get_version"), &UndoRedo::get_version);
ClassDB::bind_method(D_METHOD("redo"), &UndoRedo::redo);
diff --git a/core/undo_redo.h b/core/undo_redo.h
index 22dcd60472..f09fca9a78 100644
--- a/core/undo_redo.h
+++ b/core/undo_redo.h
@@ -112,7 +112,7 @@ public:
bool redo();
bool undo();
String get_current_action_name() const;
- void clear_history();
+ void clear_history(bool p_increase_version = true);
uint64_t get_version() const;
diff --git a/doc/Doxyfile b/doc/Doxyfile
index c1904f17c9..a7aa204741 100644
--- a/doc/Doxyfile
+++ b/doc/Doxyfile
@@ -38,7 +38,7 @@ PROJECT_NAME = Godot
# could be handy for archiving the generated documentation or if some version
# control system is used.
-PROJECT_NUMBER =
+PROJECT_NUMBER =
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
@@ -162,7 +162,7 @@ FULL_PATH_NAMES = YES
# will be relative from the directory where doxygen is started.
# This tag requires that the tag FULL_PATH_NAMES is set to YES.
-STRIP_FROM_PATH =
+STRIP_FROM_PATH =
# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
# path mentioned in the documentation of a class, which tells the reader which
@@ -171,7 +171,7 @@ STRIP_FROM_PATH =
# specify the list of include paths that are normally passed to the compiler
# using the -I flag.
-STRIP_FROM_INC_PATH =
+STRIP_FROM_INC_PATH =
# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
# less readable) file names. This can be useful is your file systems doesn't
@@ -238,13 +238,13 @@ TAB_SIZE = 4
# "Side Effects:". You can put \n's in the value part of an alias to insert
# newlines.
-ALIASES =
+ALIASES =
# This tag can be used to specify a number of word-keyword mappings (TCL only).
# A mapping has the form "name=value". For example adding "class=itcl::class"
# will allow you to use the command class in the itcl::class meaning.
-TCL_SUBST =
+TCL_SUBST =
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
# only. Doxygen will then generate output that is more tailored for C. For
@@ -291,7 +291,7 @@ OPTIMIZE_OUTPUT_VHDL = NO
# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
# the files are not read by doxygen.
-EXTENSION_MAPPING =
+EXTENSION_MAPPING =
# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
# according to the Markdown format, which allows for more readable
@@ -632,7 +632,7 @@ GENERATE_DEPRECATEDLIST= YES
# sections, marked by \if <section_label> ... \endif and \cond <section_label>
# ... \endcond blocks.
-ENABLED_SECTIONS =
+ENABLED_SECTIONS =
# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
# initial value of a variable or macro / define can have for it to appear in the
@@ -674,7 +674,7 @@ SHOW_NAMESPACES = YES
# by doxygen. Whatever the program writes to standard output is used as the file
# version. For an example see the documentation.
-FILE_VERSION_FILTER =
+FILE_VERSION_FILTER =
# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
# by doxygen. The layout file controls the global structure of the generated
@@ -687,7 +687,7 @@ FILE_VERSION_FILTER =
# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
# tag is left empty.
-LAYOUT_FILE =
+LAYOUT_FILE =
# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
# the reference definitions. This must be a list of .bib files. The .bib
@@ -697,7 +697,7 @@ LAYOUT_FILE =
# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
# search path. See also \cite for info how to create references.
-CITE_BIB_FILES =
+CITE_BIB_FILES =
#---------------------------------------------------------------------------
# Configuration options related to warning and progress messages
@@ -756,7 +756,7 @@ WARN_FORMAT = "$file:$line: $text"
# messages should be written. If left blank the output is written to standard
# error (stderr).
-WARN_LOGFILE =
+WARN_LOGFILE =
#---------------------------------------------------------------------------
# Configuration options related to the input files
@@ -844,7 +844,7 @@ RECURSIVE = YES
# Note that relative paths are relative to the directory from which doxygen is
# run.
-EXCLUDE =
+EXCLUDE =
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
# directories that are symbolic links (a Unix file system feature) are excluded
@@ -860,7 +860,7 @@ EXCLUDE_SYMLINKS = NO
# Note that the wildcards are matched against the file with absolute path, so to
# exclude all test directories for example use the pattern */test/*
-EXCLUDE_PATTERNS =
+EXCLUDE_PATTERNS =
# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
# (namespaces, classes, functions, etc.) that should be excluded from the
@@ -871,13 +871,13 @@ EXCLUDE_PATTERNS =
# Note that the wildcards are matched against the file with absolute path, so to
# exclude all test directories use the pattern */test/*
-EXCLUDE_SYMBOLS =
+EXCLUDE_SYMBOLS =
# The EXAMPLE_PATH tag can be used to specify one or more files or directories
# that contain example code fragments that are included (see the \include
# command).
-EXAMPLE_PATH =
+EXAMPLE_PATH =
# If the value of the EXAMPLE_PATH tag contains directories, you can use the
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
@@ -897,7 +897,7 @@ EXAMPLE_RECURSIVE = NO
# that contain images that are to be included in the documentation (see the
# \image command).
-IMAGE_PATH =
+IMAGE_PATH =
# The INPUT_FILTER tag can be used to specify a program that doxygen should
# invoke to filter for each input file. Doxygen will invoke the filter program
@@ -914,7 +914,7 @@ IMAGE_PATH =
# code is scanned, but not when the output code is generated. If lines are added
# or removed, the anchors will not be placed correctly.
-INPUT_FILTER =
+INPUT_FILTER =
# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
# basis. Doxygen will compare the file name with each pattern and apply the
@@ -923,7 +923,7 @@ INPUT_FILTER =
# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
# patterns match the file name, INPUT_FILTER is applied.
-FILTER_PATTERNS =
+FILTER_PATTERNS =
# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
# INPUT_FILTER) will also be used to filter the input files that are used for
@@ -938,7 +938,7 @@ FILTER_SOURCE_FILES = NO
# *.ext= (so without naming a filter).
# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
-FILTER_SOURCE_PATTERNS =
+FILTER_SOURCE_PATTERNS =
# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
# is part of the input, its contents will be placed on the main page
@@ -1050,7 +1050,7 @@ CLANG_ASSISTED_PARSING = NO
# specified with INPUT and INCLUDE_PATH.
# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
-CLANG_OPTIONS =
+CLANG_OPTIONS =
#---------------------------------------------------------------------------
# Configuration options related to the alphabetical class index
@@ -1076,7 +1076,7 @@ COLS_IN_ALPHA_INDEX = 5
# while generating the index headers.
# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
-IGNORE_PREFIX =
+IGNORE_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the HTML output
@@ -1120,7 +1120,7 @@ HTML_FILE_EXTENSION = .html
# of the possible markers and block names see the documentation.
# This tag requires that the tag GENERATE_HTML is set to YES.
-HTML_HEADER =
+HTML_HEADER =
# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
# generated HTML page. If the tag is left blank doxygen will generate a standard
@@ -1130,7 +1130,7 @@ HTML_HEADER =
# that doxygen normally uses.
# This tag requires that the tag GENERATE_HTML is set to YES.
-HTML_FOOTER =
+HTML_FOOTER =
# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
# sheet that is used by each HTML page. It can be used to fine-tune the look of
@@ -1142,7 +1142,7 @@ HTML_FOOTER =
# obsolete.
# This tag requires that the tag GENERATE_HTML is set to YES.
-HTML_STYLESHEET =
+HTML_STYLESHEET =
# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
# cascading style sheets that are included after the standard style sheets
@@ -1155,7 +1155,7 @@ HTML_STYLESHEET =
# list). For an example see the documentation.
# This tag requires that the tag GENERATE_HTML is set to YES.
-HTML_EXTRA_STYLESHEET =
+HTML_EXTRA_STYLESHEET =
# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
# other source files which should be copied to the HTML output directory. Note
@@ -1165,7 +1165,7 @@ HTML_EXTRA_STYLESHEET =
# files will be copied as-is; there are no commands or markers available.
# This tag requires that the tag GENERATE_HTML is set to YES.
-HTML_EXTRA_FILES =
+HTML_EXTRA_FILES =
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
# will adjust the colors in the style sheet and background images according to
@@ -1293,7 +1293,7 @@ GENERATE_HTMLHELP = NO
# written to the html output directory.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
-CHM_FILE =
+CHM_FILE =
# The HHC_LOCATION tag can be used to specify the location (absolute path
# including file name) of the HTML help compiler (hhc.exe). If non-empty,
@@ -1301,7 +1301,7 @@ CHM_FILE =
# The file has to be specified with full path.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
-HHC_LOCATION =
+HHC_LOCATION =
# The GENERATE_CHI flag controls if a separate .chi index file is generated
# (YES) or that it should be included in the master .chm file (NO).
@@ -1314,7 +1314,7 @@ GENERATE_CHI = NO
# and project file content.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
-CHM_INDEX_ENCODING =
+CHM_INDEX_ENCODING =
# The BINARY_TOC flag controls whether a binary table of contents is generated
# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
@@ -1345,7 +1345,7 @@ GENERATE_QHP = NO
# the HTML output folder.
# This tag requires that the tag GENERATE_QHP is set to YES.
-QCH_FILE =
+QCH_FILE =
# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
# Project output. For more information please see Qt Help Project / Namespace
@@ -1370,7 +1370,7 @@ QHP_VIRTUAL_FOLDER = doc
# filters).
# This tag requires that the tag GENERATE_QHP is set to YES.
-QHP_CUST_FILTER_NAME =
+QHP_CUST_FILTER_NAME =
# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
# custom filter to add. For more information please see Qt Help Project / Custom
@@ -1378,21 +1378,21 @@ QHP_CUST_FILTER_NAME =
# filters).
# This tag requires that the tag GENERATE_QHP is set to YES.
-QHP_CUST_FILTER_ATTRS =
+QHP_CUST_FILTER_ATTRS =
# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
# project's filter section matches. Qt Help Project / Filter Attributes (see:
# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
# This tag requires that the tag GENERATE_QHP is set to YES.
-QHP_SECT_FILTER_ATTRS =
+QHP_SECT_FILTER_ATTRS =
# The QHG_LOCATION tag can be used to specify the location of Qt's
# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
# generated .qhp file.
# This tag requires that the tag GENERATE_QHP is set to YES.
-QHG_LOCATION =
+QHG_LOCATION =
# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
# generated, together with the HTML files, they form an Eclipse help plugin. To
@@ -1525,7 +1525,7 @@ MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
# This tag requires that the tag USE_MATHJAX is set to YES.
-MATHJAX_EXTENSIONS =
+MATHJAX_EXTENSIONS =
# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
# of code that will be used on startup of the MathJax code. See the MathJax site
@@ -1533,7 +1533,7 @@ MATHJAX_EXTENSIONS =
# example see the documentation.
# This tag requires that the tag USE_MATHJAX is set to YES.
-MATHJAX_CODEFILE =
+MATHJAX_CODEFILE =
# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
# the HTML output. The underlying search engine uses javascript and DHTML and
@@ -1593,7 +1593,7 @@ EXTERNAL_SEARCH = NO
# Searching" for details.
# This tag requires that the tag SEARCHENGINE is set to YES.
-SEARCHENGINE_URL =
+SEARCHENGINE_URL =
# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
# search data is written to a file for indexing by an external tool. With the
@@ -1609,7 +1609,7 @@ SEARCHDATA_FILE = searchdata.xml
# projects and redirect the results back to the right project.
# This tag requires that the tag SEARCHENGINE is set to YES.
-EXTERNAL_SEARCH_ID =
+EXTERNAL_SEARCH_ID =
# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
# projects other than the one defined by this configuration file, but that are
@@ -1619,7 +1619,7 @@ EXTERNAL_SEARCH_ID =
# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
# This tag requires that the tag SEARCHENGINE is set to YES.
-EXTRA_SEARCH_MAPPINGS =
+EXTRA_SEARCH_MAPPINGS =
#---------------------------------------------------------------------------
# Configuration options related to the LaTeX output
@@ -1680,7 +1680,7 @@ PAPER_TYPE = a4
# If left blank no extra packages will be included.
# This tag requires that the tag GENERATE_LATEX is set to YES.
-EXTRA_PACKAGES =
+EXTRA_PACKAGES =
# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
# generated LaTeX document. The header should contain everything until the first
@@ -1696,7 +1696,7 @@ EXTRA_PACKAGES =
# to HTML_HEADER.
# This tag requires that the tag GENERATE_LATEX is set to YES.
-LATEX_HEADER =
+LATEX_HEADER =
# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
# generated LaTeX document. The footer should contain everything after the last
@@ -1707,7 +1707,7 @@ LATEX_HEADER =
# Note: Only use a user-defined footer if you know what you are doing!
# This tag requires that the tag GENERATE_LATEX is set to YES.
-LATEX_FOOTER =
+LATEX_FOOTER =
# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
# LaTeX style sheets that are included after the standard style sheets created
@@ -1718,7 +1718,7 @@ LATEX_FOOTER =
# list).
# This tag requires that the tag GENERATE_LATEX is set to YES.
-LATEX_EXTRA_STYLESHEET =
+LATEX_EXTRA_STYLESHEET =
# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
# other source files which should be copied to the LATEX_OUTPUT output
@@ -1726,7 +1726,7 @@ LATEX_EXTRA_STYLESHEET =
# markers available.
# This tag requires that the tag GENERATE_LATEX is set to YES.
-LATEX_EXTRA_FILES =
+LATEX_EXTRA_FILES =
# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
@@ -1826,14 +1826,14 @@ RTF_HYPERLINKS = NO
# default style sheet that doxygen normally uses.
# This tag requires that the tag GENERATE_RTF is set to YES.
-RTF_STYLESHEET_FILE =
+RTF_STYLESHEET_FILE =
# Set optional variables used in the generation of an RTF document. Syntax is
# similar to doxygen's config file. A template extensions file can be generated
# using doxygen -e rtf extensionFile.
# This tag requires that the tag GENERATE_RTF is set to YES.
-RTF_EXTENSIONS_FILE =
+RTF_EXTENSIONS_FILE =
# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code
# with syntax highlighting in the RTF output.
@@ -1878,7 +1878,7 @@ MAN_EXTENSION = .3
# MAN_EXTENSION with the initial . removed.
# This tag requires that the tag GENERATE_MAN is set to YES.
-MAN_SUBDIR =
+MAN_SUBDIR =
# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
# will generate one additional man file for each entity documented in the real
@@ -1991,7 +1991,7 @@ PERLMOD_PRETTY = YES
# overwrite each other's variables.
# This tag requires that the tag GENERATE_PERLMOD is set to YES.
-PERLMOD_MAKEVAR_PREFIX =
+PERLMOD_MAKEVAR_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
@@ -2032,7 +2032,7 @@ SEARCH_INCLUDES = YES
# preprocessor.
# This tag requires that the tag SEARCH_INCLUDES is set to YES.
-INCLUDE_PATH =
+INCLUDE_PATH =
# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
# patterns (like *.h and *.hpp) to filter out the header-files in the
@@ -2040,7 +2040,7 @@ INCLUDE_PATH =
# used.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
-INCLUDE_FILE_PATTERNS =
+INCLUDE_FILE_PATTERNS =
# The PREDEFINED tag can be used to specify one or more macro names that are
# defined before the preprocessor is started (similar to the -D option of e.g.
@@ -2050,7 +2050,7 @@ INCLUDE_FILE_PATTERNS =
# recursively expanded use the := operator instead of the = operator.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
-PREDEFINED =
+PREDEFINED =
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
# tag can be used to specify a list of macro names that should be expanded. The
@@ -2059,7 +2059,7 @@ PREDEFINED =
# definition found in the source code.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
-EXPAND_AS_DEFINED =
+EXPAND_AS_DEFINED =
# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
# remove all references to function-like macros that are alone on a line, have
@@ -2088,13 +2088,13 @@ SKIP_FUNCTION_MACROS = YES
# the path). If a tag file is not located in the directory in which doxygen is
# run, you must also specify the path to the tagfile here.
-TAGFILES =
+TAGFILES =
# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
# tag file that is based on the input files it reads. See section "Linking to
# external documentation" for more information about the usage of tag files.
-GENERATE_TAGFILE =
+GENERATE_TAGFILE =
# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
# the class index. If set to NO, only the inherited external classes will be
@@ -2143,14 +2143,14 @@ CLASS_DIAGRAMS = YES
# the mscgen tool resides. If left empty the tool is assumed to be found in the
# default search path.
-MSCGEN_PATH =
+MSCGEN_PATH =
# You can include diagrams made with dia in doxygen documentation. Doxygen will
# then run dia to produce the diagram and insert it in the documentation. The
# DIA_PATH tag allows you to specify the directory where the dia binary resides.
# If left empty dia is assumed to be found in the default search path.
-DIA_PATH =
+DIA_PATH =
# If set to YES the inheritance and collaboration graphs will hide inheritance
# and usage relations if the target is undocumented or is not a class.
@@ -2199,7 +2199,7 @@ DOT_FONTSIZE = 10
# the path where dot can find it using this tag.
# This tag requires that the tag HAVE_DOT is set to YES.
-DOT_FONTPATH =
+DOT_FONTPATH =
# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
# each documented class showing the direct and indirect inheritance relations.
@@ -2337,26 +2337,26 @@ INTERACTIVE_SVG = NO
# found. If left blank, it is assumed the dot tool can be found in the path.
# This tag requires that the tag HAVE_DOT is set to YES.
-DOT_PATH =
+DOT_PATH =
# The DOTFILE_DIRS tag can be used to specify one or more directories that
# contain dot files that are included in the documentation (see the \dotfile
# command).
# This tag requires that the tag HAVE_DOT is set to YES.
-DOTFILE_DIRS =
+DOTFILE_DIRS =
# The MSCFILE_DIRS tag can be used to specify one or more directories that
# contain msc files that are included in the documentation (see the \mscfile
# command).
-MSCFILE_DIRS =
+MSCFILE_DIRS =
# The DIAFILE_DIRS tag can be used to specify one or more directories that
# contain dia files that are included in the documentation (see the \diafile
# command).
-DIAFILE_DIRS =
+DIAFILE_DIRS =
# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
# path where java can find the plantuml.jar file. If left blank, it is assumed
@@ -2364,12 +2364,12 @@ DIAFILE_DIRS =
# generate a warning when it encounters a \startuml command in this case and
# will not generate output for the diagram.
-PLANTUML_JAR_PATH =
+PLANTUML_JAR_PATH =
# When using plantuml, the specified paths are searched for files specified by
# the !include statement in a plantuml block.
-PLANTUML_INCLUDE_PATH =
+PLANTUML_INCLUDE_PATH =
# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
# that will be shown in the graph. If the number of nodes in a graph becomes
diff --git a/doc/classes/ARVRInterface.xml b/doc/classes/ARVRInterface.xml
index 413370ed0b..bf72902410 100644
--- a/doc/classes/ARVRInterface.xml
+++ b/doc/classes/ARVRInterface.xml
@@ -45,8 +45,8 @@
</return>
<description>
Call this to initialize this interface. The first interface that is initialized is identified as the primary interface and it will be used for rendering output.
- After initializing the interface you want to use you then need to enable the AR/VR mode of a viewport and rendering should commence.
- Note that you must enable the AR/VR mode on the main viewport for any device that uses the main output of Godot such as for mobile VR.
+ After initializing the interface you want to use you then need to enable the AR/VR mode of a viewport and rendering should commence.
+ Note that you must enable the AR/VR mode on the main viewport for any device that uses the main output of Godot such as for mobile VR.
If you do this for a platform that handles its own output (such as OpenVR) Godot will show just one eye without distortion on screen. Alternatively you can add a separate viewport node to your scene and enable AR/VR on that viewport and it will be used to output to the HMD leaving you free to do anything you like in the main window such as using a separate camera as a spectator camera or render out something completely different.
While currently not used you can activate additional interfaces, you may wish to do this if you want to track controllers from other platforms. However at this point in time only one interface can render to an HMD.
</description>
diff --git a/doc/classes/Animation.xml b/doc/classes/Animation.xml
index f189e6451d..169fbcd5a8 100644
--- a/doc/classes/Animation.xml
+++ b/doc/classes/Animation.xml
@@ -7,7 +7,7 @@
An Animation resource contains data used to animate everything in the engine. Animations are divided into tracks, and each track must be linked to a node. The state of that node can be changed through time, by adding timed keys (events) to the track.
[codeblock]
# This creates an animation that makes the node "Enemy" move to the right by
- # 100 pixels in 1 second.
+ # 100 pixels in 1 second.
var animation = Animation.new()
var track_index = animation.add_track(Animation.TYPE_VALUE)
animation.track_set_path(track_index, "Enemy:position.x")
diff --git a/doc/classes/AudioEffectReverb.xml b/doc/classes/AudioEffectReverb.xml
index 87c622e3bb..008c644466 100644
--- a/doc/classes/AudioEffectReverb.xml
+++ b/doc/classes/AudioEffectReverb.xml
@@ -15,7 +15,7 @@
</methods>
<members>
<member name="damping" type="float" setter="set_damping" getter="get_damping">
- Defines how reflective the imaginary room's walls are. Value can range from 0 to 1. Default value: [code]1[/code].
+ Defines how reflective the imaginary room's walls are. Value can range from 0 to 1. Default value: [code]1[/code].
</member>
<member name="dry" type="float" setter="set_dry" getter="get_dry">
Output percent of original sound. At 0, only modified sound is outputted. Value can range from 0 to 1. Default value: [code]1[/code].
diff --git a/doc/classes/BaseButton.xml b/doc/classes/BaseButton.xml
index 3364770280..ffdc010987 100644
--- a/doc/classes/BaseButton.xml
+++ b/doc/classes/BaseButton.xml
@@ -68,6 +68,9 @@
<member name="toggle_mode" type="bool" setter="set_toggle_mode" getter="is_toggle_mode">
If [code]true[/code] the button is in toggle mode. Makes the button flip state between pressed and unpressed each time its area is clicked.
</member>
+ <member name="shortcut_in_tooltip" type="bool" setter="set_shortcut_in_tooltip" getter="is_shortcut_in_tooltip_enabled">
+ If [code]true[/code] the button will add information about its shortcut in the tooltip.
+ </member>
</members>
<signals>
<signal name="button_down">
diff --git a/doc/classes/Dictionary.xml b/doc/classes/Dictionary.xml
index cc58c56404..a9e2a38dcf 100644
--- a/doc/classes/Dictionary.xml
+++ b/doc/classes/Dictionary.xml
@@ -41,6 +41,17 @@
Erase a dictionary key/value pair by key.
</description>
</method>
+ <method name="get">
+ <return type="Variant">
+ </return>
+ <argument index="0" name="key" type="Variant">
+ </argument>
+ <argument index="1" name="default" type="Variant" default="Null">
+ </argument>
+ <description>
+ Returns the current value for the specified key in the [code]Dictionary[/code]. If the key does not exist, the method returns the value of the optional default argument, or Null if it is omitted.
+ </description>
+ </method>
<method name="has">
<return type="bool">
</return>
@@ -87,17 +98,6 @@
Return the list of values in the [code]Dictionary[/code].
</description>
</method>
- <method name="get">
- <return type="Variant">
- </return>
- <argument index="0" name="key" type="Variant">
- </argument>
- <argument index="1" name="default" type="Variant" default="null">
- </argument>
- <description>
- Returns the current value for the specified key in the [code]Dictionary[/code]. If the key does not exist, the method returns the value of the optional default argument, or Null if it is omitted.
- </description>
- </method>
</methods>
<constants>
</constants>
diff --git a/doc/classes/DynamicFontData.xml b/doc/classes/DynamicFontData.xml
index 7b34d02316..5fcccf7db9 100644
--- a/doc/classes/DynamicFontData.xml
+++ b/doc/classes/DynamicFontData.xml
@@ -13,6 +13,9 @@
<methods>
</methods>
<members>
+ <member name="antialiased" type="bool" setter="set_antialiased" getter="is_antialiased">
+ Controls whether the font should be rendered with anti-aliasing.
+ </member>
<member name="font_path" type="String" setter="set_font_path" getter="get_font_path">
The path to the vector font file.
</member>
diff --git a/doc/classes/Environment.xml b/doc/classes/Environment.xml
index 4c2c83e55f..949c93761e 100644
--- a/doc/classes/Environment.xml
+++ b/doc/classes/Environment.xml
@@ -5,7 +5,6 @@
</brief_description>
<description>
Resource for environment nodes (like [WorldEnvironment]) that define multiple environment operations (such as background [Sky] or [Color], ambient light, fog, depth-of-field...). These parameters affect the final render of the scene. The order of these operations is:
-
- DOF Blur
- Motion Blur
- Bloom
@@ -120,6 +119,8 @@
<member name="fog_depth_enabled" type="bool" setter="set_fog_depth_enabled" getter="is_fog_depth_enabled">
Enables the fog depth.
</member>
+ <member name="fog_depth_end" type="float" setter="set_fog_depth_end" getter="get_fog_depth_end">
+ </member>
<member name="fog_enabled" type="bool" setter="set_fog_enabled" getter="is_fog_enabled">
Enables the fog. Needs fog_height_enabled and/or for_depth_enabled to actually display fog.
</member>
diff --git a/doc/classes/File.xml b/doc/classes/File.xml
index 1745389833..058bb09090 100644
--- a/doc/classes/File.xml
+++ b/doc/classes/File.xml
@@ -330,7 +330,7 @@
<method name="store_csv_line">
<return type="void">
</return>
- <argument index="0" name="values" type="PoolStringArray" default="&quot;,&quot;">
+ <argument index="0" name="values" type="PoolStringArray">
</argument>
<argument index="1" name="delim" type="String" default="&quot;,&quot;">
</argument>
diff --git a/doc/classes/Generic6DOFJoint.xml b/doc/classes/Generic6DOFJoint.xml
index 0863ead4ec..e1046e282a 100644
--- a/doc/classes/Generic6DOFJoint.xml
+++ b/doc/classes/Generic6DOFJoint.xml
@@ -113,6 +113,30 @@
<member name="angular_motor_z/target_velocity" type="float" setter="set_param_z" getter="get_param_z">
Target speed for the motor at the z-axis.
</member>
+ <member name="angular_spring_x/damping" type="float" setter="set_param_x" getter="get_param_x">
+ </member>
+ <member name="angular_spring_x/enabled" type="bool" setter="set_flag_x" getter="get_flag_x">
+ </member>
+ <member name="angular_spring_x/equilibrium_point" type="float" setter="set_param_x" getter="get_param_x">
+ </member>
+ <member name="angular_spring_x/stiffness" type="float" setter="set_param_x" getter="get_param_x">
+ </member>
+ <member name="angular_spring_y/damping" type="float" setter="set_param_y" getter="get_param_y">
+ </member>
+ <member name="angular_spring_y/enabled" type="bool" setter="set_flag_y" getter="get_flag_y">
+ </member>
+ <member name="angular_spring_y/equilibrium_point" type="float" setter="set_param_y" getter="get_param_y">
+ </member>
+ <member name="angular_spring_y/stiffness" type="float" setter="set_param_y" getter="get_param_y">
+ </member>
+ <member name="angular_spring_z/damping" type="float" setter="set_param_z" getter="get_param_z">
+ </member>
+ <member name="angular_spring_z/enabled" type="bool" setter="set_flag_z" getter="get_flag_z">
+ </member>
+ <member name="angular_spring_z/equilibrium_point" type="float" setter="set_param_z" getter="get_param_z">
+ </member>
+ <member name="angular_spring_z/stiffness" type="float" setter="set_param_z" getter="get_param_z">
+ </member>
<member name="linear_limit_x/damping" type="float" setter="set_param_x" getter="get_param_x">
The amount of damping that happens at the x-motion.
</member>
@@ -194,6 +218,30 @@
<member name="linear_motor_z/target_velocity" type="float" setter="set_param_z" getter="get_param_z">
The speed that the linear motor will attempt to reach on the z-axis.
</member>
+ <member name="linear_spring_x/damping" type="float" setter="set_param_x" getter="get_param_x">
+ </member>
+ <member name="linear_spring_x/enabled" type="bool" setter="set_flag_x" getter="get_flag_x">
+ </member>
+ <member name="linear_spring_x/equilibrium_point" type="float" setter="set_param_x" getter="get_param_x">
+ </member>
+ <member name="linear_spring_x/stiffness" type="float" setter="set_param_x" getter="get_param_x">
+ </member>
+ <member name="linear_spring_y/damping" type="float" setter="set_param_y" getter="get_param_y">
+ </member>
+ <member name="linear_spring_y/enabled" type="bool" setter="set_flag_y" getter="get_flag_y">
+ </member>
+ <member name="linear_spring_y/equilibrium_point" type="float" setter="set_param_y" getter="get_param_y">
+ </member>
+ <member name="linear_spring_y/stiffness" type="float" setter="set_param_y" getter="get_param_y">
+ </member>
+ <member name="linear_spring_z/damping" type="float" setter="set_param_z" getter="get_param_z">
+ </member>
+ <member name="linear_spring_z/enabled" type="bool" setter="set_flag_z" getter="get_flag_z">
+ </member>
+ <member name="linear_spring_z/equilibrium_point" type="float" setter="set_param_z" getter="get_param_z">
+ </member>
+ <member name="linear_spring_z/stiffness" type="float" setter="set_param_z" getter="get_param_z">
+ </member>
</members>
<constants>
<constant name="PARAM_LINEAR_LOWER_LIMIT" value="0" enum="Param">
@@ -217,34 +265,34 @@
<constant name="PARAM_LINEAR_MOTOR_FORCE_LIMIT" value="6" enum="Param">
The maximum force the linear motor will apply while trying to reach the velocity target.
</constant>
- <constant name="PARAM_ANGULAR_LOWER_LIMIT" value="7" enum="Param">
+ <constant name="PARAM_ANGULAR_LOWER_LIMIT" value="10" enum="Param">
The minimum rotation in negative direction to break loose and rotate around the axes.
</constant>
- <constant name="PARAM_ANGULAR_UPPER_LIMIT" value="8" enum="Param">
+ <constant name="PARAM_ANGULAR_UPPER_LIMIT" value="11" enum="Param">
The minimum rotation in positive direction to break loose and rotate around the axes.
</constant>
- <constant name="PARAM_ANGULAR_LIMIT_SOFTNESS" value="9" enum="Param">
+ <constant name="PARAM_ANGULAR_LIMIT_SOFTNESS" value="12" enum="Param">
The speed of all rotations across the axes.
</constant>
- <constant name="PARAM_ANGULAR_DAMPING" value="10" enum="Param">
+ <constant name="PARAM_ANGULAR_DAMPING" value="13" enum="Param">
The amount of rotational damping across the axes. The lower, the more dampening occurs.
</constant>
- <constant name="PARAM_ANGULAR_RESTITUTION" value="11" enum="Param">
+ <constant name="PARAM_ANGULAR_RESTITUTION" value="14" enum="Param">
The amount of rotational restitution across the axes. The lower, the more restitution occurs.
</constant>
- <constant name="PARAM_ANGULAR_FORCE_LIMIT" value="12" enum="Param">
+ <constant name="PARAM_ANGULAR_FORCE_LIMIT" value="15" enum="Param">
The maximum amount of force that can occur, when rotating around the axes.
</constant>
- <constant name="PARAM_ANGULAR_ERP" value="13" enum="Param">
+ <constant name="PARAM_ANGULAR_ERP" value="16" enum="Param">
When rotating across the axes, this error tolerance factor defines how much the correction gets slowed down. The lower, the slower.
</constant>
- <constant name="PARAM_ANGULAR_MOTOR_TARGET_VELOCITY" value="14" enum="Param">
+ <constant name="PARAM_ANGULAR_MOTOR_TARGET_VELOCITY" value="17" enum="Param">
Target speed for the motor at the axes.
</constant>
- <constant name="PARAM_ANGULAR_MOTOR_FORCE_LIMIT" value="15" enum="Param">
+ <constant name="PARAM_ANGULAR_MOTOR_FORCE_LIMIT" value="18" enum="Param">
Maximum acceleration for the motor at the axes.
</constant>
- <constant name="PARAM_MAX" value="16" enum="Param">
+ <constant name="PARAM_MAX" value="22" enum="Param">
End flag of PARAM_* constants, used internally.
</constant>
<constant name="FLAG_ENABLE_LINEAR_LIMIT" value="0" enum="Flag">
@@ -253,12 +301,16 @@
<constant name="FLAG_ENABLE_ANGULAR_LIMIT" value="1" enum="Flag">
If [code]set[/code] there is rotational motion possible.
</constant>
- <constant name="FLAG_ENABLE_MOTOR" value="2" enum="Flag">
+ <constant name="FLAG_ENABLE_LINEAR_SPRING" value="3" enum="Flag">
+ </constant>
+ <constant name="FLAG_ENABLE_ANGULAR_SPRING" value="2" enum="Flag">
+ </constant>
+ <constant name="FLAG_ENABLE_MOTOR" value="4" enum="Flag">
If [code]set[/code] there is a rotational motor across these axes.
</constant>
- <constant name="FLAG_ENABLE_LINEAR_MOTOR" value="3" enum="Flag">
+ <constant name="FLAG_ENABLE_LINEAR_MOTOR" value="5" enum="Flag">
</constant>
- <constant name="FLAG_MAX" value="4" enum="Flag">
+ <constant name="FLAG_MAX" value="6" enum="Flag">
End flag of FLAG_* constants, used internally.
</constant>
</constants>
diff --git a/doc/classes/Object.xml b/doc/classes/Object.xml
index fcd105d66b..86de830d56 100644
--- a/doc/classes/Object.xml
+++ b/doc/classes/Object.xml
@@ -348,6 +348,16 @@
If set to true, signal emission is blocked.
</description>
</method>
+ <method name="set_deferred">
+ <return type="void">
+ </return>
+ <argument index="0" name="property" type="String">
+ </argument>
+ <argument index="1" name="value" type="Variant">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="set_indexed">
<return type="void">
</return>
diff --git a/doc/classes/OrientedPathFollow.xml b/doc/classes/OrientedPathFollow.xml
index 85d60936ad..bc6af4711b 100644
--- a/doc/classes/OrientedPathFollow.xml
+++ b/doc/classes/OrientedPathFollow.xml
@@ -4,7 +4,7 @@
Oriented point sampler for a [Path].
</brief_description>
<description>
- This node behaves like [PathFollow], except it uses its parent [Path] up vector information to enforce orientation.
+ This node behaves like [PathFollow], except it uses its parent [Path] up vector information to enforce orientation.
Make sure to check if the curve of this node's parent [Path] has up vectors enabled. See [PathFollow] and [Curve3D] for further information.
</description>
<tutorials>
diff --git a/doc/classes/PHashTranslation.xml b/doc/classes/PHashTranslation.xml
index 18c72a0576..e5745375b0 100644
--- a/doc/classes/PHashTranslation.xml
+++ b/doc/classes/PHashTranslation.xml
@@ -17,6 +17,7 @@
<argument index="0" name="from" type="Translation">
</argument>
<description>
+ Generates and sets an optimized translation from the given [Translation] resource.
</description>
</method>
</methods>
diff --git a/doc/classes/PhysicsServer.xml b/doc/classes/PhysicsServer.xml
index c836414dd2..7dfc8e66d4 100644
--- a/doc/classes/PhysicsServer.xml
+++ b/doc/classes/PhysicsServer.xml
@@ -1401,31 +1401,31 @@
<constant name="G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT" value="6" enum="G6DOFJointAxisParam">
The maximum force that the linear motor can apply while trying to reach the target velocity.
</constant>
- <constant name="G6DOF_JOINT_ANGULAR_LOWER_LIMIT" value="7" enum="G6DOFJointAxisParam">
+ <constant name="G6DOF_JOINT_ANGULAR_LOWER_LIMIT" value="10" enum="G6DOFJointAxisParam">
The minimum rotation in negative direction to break loose and rotate around the axes.
</constant>
- <constant name="G6DOF_JOINT_ANGULAR_UPPER_LIMIT" value="8" enum="G6DOFJointAxisParam">
+ <constant name="G6DOF_JOINT_ANGULAR_UPPER_LIMIT" value="11" enum="G6DOFJointAxisParam">
The minimum rotation in positive direction to break loose and rotate around the axes.
</constant>
- <constant name="G6DOF_JOINT_ANGULAR_LIMIT_SOFTNESS" value="9" enum="G6DOFJointAxisParam">
+ <constant name="G6DOF_JOINT_ANGULAR_LIMIT_SOFTNESS" value="12" enum="G6DOFJointAxisParam">
A factor that gets multiplied onto all rotations across the axes.
</constant>
- <constant name="G6DOF_JOINT_ANGULAR_DAMPING" value="10" enum="G6DOFJointAxisParam">
+ <constant name="G6DOF_JOINT_ANGULAR_DAMPING" value="13" enum="G6DOFJointAxisParam">
The amount of rotational damping across the axes. The lower, the more dampening occurs.
</constant>
- <constant name="G6DOF_JOINT_ANGULAR_RESTITUTION" value="11" enum="G6DOFJointAxisParam">
+ <constant name="G6DOF_JOINT_ANGULAR_RESTITUTION" value="14" enum="G6DOFJointAxisParam">
The amount of rotational restitution across the axes. The lower, the more restitution occurs.
</constant>
- <constant name="G6DOF_JOINT_ANGULAR_FORCE_LIMIT" value="12" enum="G6DOFJointAxisParam">
+ <constant name="G6DOF_JOINT_ANGULAR_FORCE_LIMIT" value="15" enum="G6DOFJointAxisParam">
The maximum amount of force that can occur, when rotating around the axes.
</constant>
- <constant name="G6DOF_JOINT_ANGULAR_ERP" value="13" enum="G6DOFJointAxisParam">
+ <constant name="G6DOF_JOINT_ANGULAR_ERP" value="16" enum="G6DOFJointAxisParam">
When correcting the crossing of limits in rotation across the axes, this error tolerance factor defines how much the correction gets slowed down. The lower, the slower.
</constant>
- <constant name="G6DOF_JOINT_ANGULAR_MOTOR_TARGET_VELOCITY" value="14" enum="G6DOFJointAxisParam">
+ <constant name="G6DOF_JOINT_ANGULAR_MOTOR_TARGET_VELOCITY" value="17" enum="G6DOFJointAxisParam">
Target speed for the motor at the axes.
</constant>
- <constant name="G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT" value="15" enum="G6DOFJointAxisParam">
+ <constant name="G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT" value="18" enum="G6DOFJointAxisParam">
Maximum acceleration for the motor at the axes.
</constant>
<constant name="G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT" value="0" enum="G6DOFJointAxisFlag">
@@ -1434,10 +1434,10 @@
<constant name="G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT" value="1" enum="G6DOFJointAxisFlag">
If [code]set[/code] there is rotational motion possible.
</constant>
- <constant name="G6DOF_JOINT_FLAG_ENABLE_MOTOR" value="2" enum="G6DOFJointAxisFlag">
+ <constant name="G6DOF_JOINT_FLAG_ENABLE_MOTOR" value="4" enum="G6DOFJointAxisFlag">
If [code]set[/code] there is a rotational motor across these axes.
</constant>
- <constant name="G6DOF_JOINT_FLAG_ENABLE_LINEAR_MOTOR" value="3" enum="G6DOFJointAxisFlag">
+ <constant name="G6DOF_JOINT_FLAG_ENABLE_LINEAR_MOTOR" value="5" enum="G6DOFJointAxisFlag">
If [code]set[/code] there is a linear motor on this axis that targets a specific velocity.
</constant>
<constant name="SHAPE_PLANE" value="0" enum="ShapeType">
diff --git a/doc/classes/SpatialMaterial.xml b/doc/classes/SpatialMaterial.xml
index 392a550ee4..3503505999 100644
--- a/doc/classes/SpatialMaterial.xml
+++ b/doc/classes/SpatialMaterial.xml
@@ -52,6 +52,10 @@
<member name="depth_enabled" type="bool" setter="set_feature" getter="get_feature">
If [code]true[/code] Depth mapping is enabled. See also [member normal_enabled].
</member>
+ <member name="depth_flip_binormal" type="bool" setter="set_depth_deep_parallax_flip_binormal" getter="get_depth_deep_parallax_flip_binormal">
+ </member>
+ <member name="depth_flip_tangent" type="bool" setter="set_depth_deep_parallax_flip_tangent" getter="get_depth_deep_parallax_flip_tangent">
+ </member>
<member name="depth_max_layers" type="int" setter="set_depth_deep_parallax_max_layers" getter="get_depth_deep_parallax_max_layers">
</member>
<member name="depth_min_layers" type="int" setter="set_depth_deep_parallax_min_layers" getter="get_depth_deep_parallax_min_layers">
diff --git a/doc/classes/StyleBoxFlat.xml b/doc/classes/StyleBoxFlat.xml
index 641d6214a4..bf544d2b78 100644
--- a/doc/classes/StyleBoxFlat.xml
+++ b/doc/classes/StyleBoxFlat.xml
@@ -5,22 +5,21 @@
</brief_description>
<description>
This stylebox can be used to achieve all kinds of looks without the need of a texture. Those properties are customizable:
- - Color
- - Border width (individual width for each border)
- - Rounded corners (individual radius for each corner)
- - Shadow
- About corner radius:
- Setting corner radius to high values is allowed. As soon as corners would overlap the stylebox will switch to a relative system. Example:
- [codeblock]
- height = 30
- corner_radius_top_left = 50
- corner_radius_bottom_left = 100
- [/codeblock]
- The relative system now would take the 1:2 ratio of the two left corners to calculate the actual corner width. Both corners added will [b]never[/b] be more than the height. Result:
- [codeblock]
- corner_radius_top_left: 10
- corner_radius_bottom_left: 20
- [/codeblock]
+ - Color
+ - Border width (individual width for each border)
+ - Rounded corners (individual radius for each corner)
+ - Shadow
+ Setting corner radius to high values is allowed. As soon as corners would overlap the stylebox will switch to a relative system. Example:
+ [codeblock]
+ height = 30
+ corner_radius_top_left = 50
+ corner_radius_bottom_left = 100
+ [/codeblock]
+ The relative system now would take the 1:2 ratio of the two left corners to calculate the actual corner width. Both corners added will [b]never[/b] be more than the height. Result:
+ [codeblock]
+ corner_radius_top_left: 10
+ corner_radius_bottom_left: 20
+ [/codeblock]
</description>
<tutorials>
</tutorials>
@@ -117,7 +116,7 @@
<member name="corner_detail" type="int" setter="set_corner_detail" getter="get_corner_detail">
This sets the amount of vertices used for each corner. Higher values result in rounder corners but take more processing power to compute. When choosing a value you should take the corner radius ([method set_corner_radius]) into account.
For corner radius smaller than 10: 4-5 should be enough
- For corner radius smaller than 30: 8-12 should be enough ...
+ For corner radius smaller than 30: 8-12 should be enough
</member>
<member name="corner_radius_bottom_left" type="int" setter="set_corner_radius" getter="get_corner_radius">
The corner radius of the bottom left corner. When set to 0 the corner is not rounded.
diff --git a/doc/classes/Translation.xml b/doc/classes/Translation.xml
index c4e9dbfb70..b57f8f3556 100644
--- a/doc/classes/Translation.xml
+++ b/doc/classes/Translation.xml
@@ -7,6 +7,8 @@
Translations are resources that can be loaded/unloaded on demand. They map a string to another string.
</description>
<tutorials>
+ <link>https://docs.godotengine.org/en/stable/tutorials/i18n/internationalizing_games.html</link>
+ <link>https://docs.godotengine.org/en/stable/tutorials/i18n/locales.html</link>
</tutorials>
<demos>
</demos>
@@ -19,7 +21,7 @@
<argument index="1" name="xlated_message" type="String">
</argument>
<description>
- Add a message for translation.
+ Adds a message if nonexistent, followed by its translation.
</description>
</method>
<method name="erase_message">
@@ -28,7 +30,7 @@
<argument index="0" name="src_message" type="String">
</argument>
<description>
- Erase a message.
+ Erases a message.
</description>
</method>
<method name="get_message" qualifiers="const">
@@ -37,25 +39,27 @@
<argument index="0" name="src_message" type="String">
</argument>
<description>
- Return a message for translation.
+ Returns a message's translation.
</description>
</method>
<method name="get_message_count" qualifiers="const">
<return type="int">
</return>
<description>
+ Returns the number of existing messages.
</description>
</method>
<method name="get_message_list" qualifiers="const">
<return type="PoolStringArray">
</return>
<description>
- Return all the messages (keys).
+ Returns all the messages (keys).
</description>
</method>
</methods>
<members>
<member name="locale" type="String" setter="set_locale" getter="get_locale">
+ The locale of the translation.
</member>
</members>
<constants>
diff --git a/doc/classes/TranslationServer.xml b/doc/classes/TranslationServer.xml
index 52d2b2cc47..c2c400ccd5 100644
--- a/doc/classes/TranslationServer.xml
+++ b/doc/classes/TranslationServer.xml
@@ -1,11 +1,14 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="TranslationServer" inherits="Object" category="Core" version="3.1">
<brief_description>
- Server that manages all translations. Translations can be set to it and removed from it.
+ Server that manages all translations.
</brief_description>
<description>
+ Server that manages all translations. Translations can be set to it and removed from it.
</description>
<tutorials>
+ <link>https://docs.godotengine.org/en/stable/tutorials/i18n/internationalizing_games.html</link>
+ <link>https://docs.godotengine.org/en/stable/tutorials/i18n/locales.html</link>
</tutorials>
<demos>
</demos>
@@ -16,18 +19,21 @@
<argument index="0" name="translation" type="Translation">
</argument>
<description>
+ Adds a [Translation] resource.
</description>
</method>
<method name="clear">
<return type="void">
</return>
<description>
+ Clears the server from all translations.
</description>
</method>
<method name="get_locale" qualifiers="const">
<return type="String">
</return>
<description>
+ Returns the current locale of the game.
</description>
</method>
<method name="get_locale_name" qualifiers="const">
@@ -36,6 +42,7 @@
<argument index="0" name="locale" type="String">
</argument>
<description>
+ Returns a locale's language and its variant (e.g. "en_US" would return "English (United States)").
</description>
</method>
<method name="remove_translation">
@@ -44,6 +51,7 @@
<argument index="0" name="translation" type="Translation">
</argument>
<description>
+ Removes the given translation from the server.
</description>
</method>
<method name="set_locale">
@@ -52,6 +60,7 @@
<argument index="0" name="locale" type="String">
</argument>
<description>
+ Sets the locale of the game.
</description>
</method>
<method name="translate" qualifiers="const">
@@ -60,6 +69,7 @@
<argument index="0" name="message" type="String">
</argument>
<description>
+ Returns the current locale's translation for the given message (key).
</description>
</method>
</methods>
diff --git a/doc/classes/Tree.xml b/doc/classes/Tree.xml
index 8051062fc4..1ad8166b91 100644
--- a/doc/classes/Tree.xml
+++ b/doc/classes/Tree.xml
@@ -315,12 +315,12 @@
<argument index="0" name="position" type="Vector2">
</argument>
<description>
- Emitted when an item is selected with right mouse button.
+ Emitted when an item is selected with the right mouse button.
</description>
</signal>
<signal name="item_selected">
<description>
- Emitted when an item is selected with right mouse button.
+ Emitted when an item is selected.
</description>
</signal>
<signal name="multi_selected">
@@ -384,6 +384,8 @@
</theme_item>
<theme_item name="custom_button_pressed" type="StyleBox">
</theme_item>
+ <theme_item name="draw_guides" type="int">
+ </theme_item>
<theme_item name="draw_relationship_lines" type="int">
</theme_item>
<theme_item name="drop_position_color" type="Color">
diff --git a/doc/classes/UndoRedo.xml b/doc/classes/UndoRedo.xml
index 0ea5c6e005..93806ac326 100644
--- a/doc/classes/UndoRedo.xml
+++ b/doc/classes/UndoRedo.xml
@@ -102,8 +102,11 @@
<method name="clear_history">
<return type="void">
</return>
+ <argument index="0" name="increase_version" type="bool" default="true">
+ </argument>
<description>
Clear the undo/redo history and associated references.
+ Passing [code]false[/code] to [code]increase_version[/code] will prevent the version number to be increased from this.
</description>
</method>
<method name="commit_action">
diff --git a/doc/classes/Viewport.xml b/doc/classes/Viewport.xml
index 2cdd8c407f..4706651c6e 100644
--- a/doc/classes/Viewport.xml
+++ b/doc/classes/Viewport.xml
@@ -125,6 +125,12 @@
<description>
</description>
</method>
+ <method name="is_input_handled" qualifiers="const">
+ <return type="bool">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="is_size_override_enabled" qualifiers="const">
<return type="bool">
</return>
@@ -147,6 +153,12 @@
<description>
</description>
</method>
+ <method name="set_input_as_handled">
+ <return type="void">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="set_size_override">
<return type="void">
</return>
@@ -222,6 +234,8 @@
<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="handle_input_locally" type="bool" setter="set_handle_input_locally" getter="is_handling_input_locally">
+ </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>
diff --git a/doc/classes/VisualServer.xml b/doc/classes/VisualServer.xml
index 46a06d63d4..b24eeaa112 100644
--- a/doc/classes/VisualServer.xml
+++ b/doc/classes/VisualServer.xml
@@ -1113,11 +1113,13 @@
</argument>
<argument index="2" name="depth_begin" type="float">
</argument>
- <argument index="3" name="depth_curve" type="float">
+ <argument index="3" name="depth_end" type="float">
</argument>
- <argument index="4" name="transmit" type="bool">
+ <argument index="4" name="depth_curve" type="float">
</argument>
- <argument index="5" name="transmit_curve" type="float">
+ <argument index="5" name="transmit" type="bool">
+ </argument>
+ <argument index="6" name="transmit_curve" type="float">
</argument>
<description>
</description>
diff --git a/drivers/gles2/shader_compiler_gles2.cpp b/drivers/gles2/shader_compiler_gles2.cpp
index 28c0274afa..d52be09cac 100644
--- a/drivers/gles2/shader_compiler_gles2.cpp
+++ b/drivers/gles2/shader_compiler_gles2.cpp
@@ -86,10 +86,11 @@ static String _mkid(const String &p_id) {
static String f2sp0(float p_float) {
- if (int(p_float) == p_float)
- return itos(p_float) + ".0";
- else
- return rtoss(p_float);
+ String num = rtoss(p_float);
+ if (num.find(".") == -1 && num.find("e") == -1) {
+ num += ".0";
+ }
+ return num;
}
static String get_constant_text(SL::DataType p_type, const Vector<SL::ConstantNode::Value> &p_values) {
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp
index 0951b8f798..e0c8d3af52 100644
--- a/drivers/gles3/rasterizer_scene_gles3.cpp
+++ b/drivers/gles3/rasterizer_scene_gles3.cpp
@@ -3039,20 +3039,17 @@ void RasterizerSceneGLES3::_setup_reflections(RID *p_reflection_probe_cull_resul
reflection_ubo.ambient[3] = rpi->probe_ptr->interior_ambient_probe_contrib;
} else {
Color ambient_linear;
- // FIXME: contrib was retrieved but never used, is it meant to be set as ambient[3]? (GH-20361)
- //float contrib = 0;
if (p_env) {
ambient_linear = p_env->ambient_color.to_linear();
ambient_linear.r *= p_env->ambient_energy;
ambient_linear.g *= p_env->ambient_energy;
ambient_linear.b *= p_env->ambient_energy;
- //contrib = p_env->ambient_sky_contribution;
}
reflection_ubo.ambient[0] = ambient_linear.r;
reflection_ubo.ambient[1] = ambient_linear.g;
reflection_ubo.ambient[2] = ambient_linear.b;
- reflection_ubo.ambient[3] = 0;
+ reflection_ubo.ambient[3] = 0; //not used in exterior mode, since it just blends with regular ambient light
}
int cell_size = reflection_atlas->size / reflection_atlas->subdiv;
@@ -3599,7 +3596,7 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
}
- if (!env || storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) {
+ if (!env || storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT] || storage->frame.current_rt->width < 4 || storage->frame.current_rt->height < 4) { //no post process on small render targets
//no environment or transparent render, simply return and convert to SRGB
glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo);
glActiveTexture(GL_TEXTURE0);
@@ -4297,8 +4294,10 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
glClearBufferfv(GL_COLOR, 0, clear_color.components); // specular
}
+ VS::EnvironmentBG bg_mode = (!env || (probe && env->bg_mode == VS::ENV_BG_CANVAS)) ? VS::ENV_BG_CLEAR_COLOR : env->bg_mode; //if no environment, or canvas while rendering a probe (invalid use case), use color.
+
if (env) {
- switch (env->bg_mode) {
+ switch (bg_mode) {
case VS::ENV_BG_COLOR_SKY:
case VS::ENV_BG_SKY:
diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp
index 9e0d36f5c8..235c799a55 100644
--- a/drivers/gles3/rasterizer_storage_gles3.cpp
+++ b/drivers/gles3/rasterizer_storage_gles3.cpp
@@ -874,8 +874,6 @@ void RasterizerStorageGLES3::texture_set_data(RID p_texture, const Ref<Image> &p
int size, ofs;
img->get_mipmap_offset_and_size(i, ofs, size);
- //print_line("mipmap: "+itos(i)+" size: "+itos(size)+" w: "+itos(mm_w)+", h: "+itos(mm_h));
-
if (texture->type == VS::TEXTURE_TYPE_2D || texture->type == VS::TEXTURE_TYPE_CUBEMAP) {
if (texture->compressed) {
@@ -1062,8 +1060,6 @@ Ref<Image> RasterizerStorageGLES3::texture_get_data(RID p_texture, int p_layer)
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
- //print_line("GET FORMAT: " + Image::get_format_name(texture->format) + " mipmaps: " + itos(texture->mipmaps));
-
for (int i = 0; i < texture->mipmaps; i++) {
int ofs = 0;
@@ -1142,8 +1138,6 @@ Ref<Image> RasterizerStorageGLES3::texture_get_data(RID p_texture, int p_layer)
glBindTexture(GL_TEXTURE_2D, temp_color_texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture->alloc_width, texture->alloc_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
- print_line(itos(texture->alloc_width) + " xx " + itos(texture->alloc_height) + " -> " + itos(real_format));
-
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, temp_color_texture, 0);
@@ -2892,9 +2886,6 @@ void RasterizerStorageGLES3::_update_material(Material *material) {
if (E->get().order < 0)
continue; // texture, does not go here
- //if (material->shader->mode == VS::SHADER_PARTICLES) {
- // print_line("uniform " + String(E->key()) + " order " + itos(E->get().order) + " offset " + itos(material->shader->ubo_offsets[E->get().order]));
- //}
//regular uniform
uint8_t *data = &local_ubo[material->shader->ubo_offsets[E->get().order]];
@@ -3866,8 +3857,6 @@ AABB RasterizerStorageGLES3::mesh_get_aabb(RID p_mesh, RID p_skeleton) const {
mtx.basis[2].z = texture[base_ofs + 2];
mtx.origin.z = texture[base_ofs + 3];
- print_line("surface " + itos(i) + " bone " + itos(j) + " aabb: " + skbones[j]);
-
AABB baabb = mtx.xform(skbones[j]);
if (first) {
laabb = baabb;
diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp
index fb6e168327..2372dfb17e 100644
--- a/drivers/gles3/shader_compiler_gles3.cpp
+++ b/drivers/gles3/shader_compiler_gles3.cpp
@@ -133,8 +133,7 @@ static String _interpstr(SL::DataInterpolation p_interp) {
switch (p_interp) {
case SL::INTERPOLATION_FLAT: return "flat ";
- case SL::INTERPOLATION_NO_PERSPECTIVE: return "noperspective ";
- case SL::INTERPOLATION_SMOOTH: return "smooth ";
+ case SL::INTERPOLATION_SMOOTH: return "";
}
return "";
}
@@ -173,10 +172,11 @@ static String _mkid(const String &p_id) {
static String f2sp0(float p_float) {
- if (int(p_float) == p_float)
- return itos(p_float) + ".0";
- else
- return rtoss(p_float);
+ String num = rtoss(p_float);
+ if (num.find(".") == -1 && num.find("e") == -1) {
+ num += ".0";
+ }
+ return num;
}
static String get_constant_text(SL::DataType p_type, const Vector<SL::ConstantNode::Value> &p_values) {
@@ -229,7 +229,7 @@ static String get_constant_text(SL::DataType p_type, const Vector<SL::ConstantNo
text += ")";
return text;
} break;
- case SL::TYPE_FLOAT: return f2sp0(p_values[0].real) + "f";
+ case SL::TYPE_FLOAT: return f2sp0(p_values[0].real);
case SL::TYPE_VEC2:
case SL::TYPE_VEC3:
case SL::TYPE_VEC4: {
diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl
index d4079c4b4f..45802ad3b5 100644
--- a/drivers/gles3/shaders/scene.glsl
+++ b/drivers/gles3/shaders/scene.glsl
@@ -1585,24 +1585,24 @@ void main() {
float alpha = 1.0;
-#if defined(DO_SIDE_CHECK)
- float side = gl_FrontFacing ? 1.0 : -1.0;
-#else
- float side = 1.0;
-#endif
-
#if defined(ALPHA_SCISSOR_USED)
float alpha_scissor = 0.5;
#endif
#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY)
- vec3 binormal = normalize(binormal_interp) * side;
- vec3 tangent = normalize(tangent_interp) * side;
+ vec3 binormal = normalize(binormal_interp);// * side;
+ vec3 tangent = normalize(tangent_interp);// * side;
#else
vec3 binormal = vec3(0.0);
vec3 tangent = vec3(0.0);
#endif
- vec3 normal = normalize(normal_interp) * side;
+ vec3 normal = normalize(normal_interp);
+
+#if defined(DO_SIDE_CHECK)
+ if (!gl_FrontFacing) {
+ normal = -normal;
+ }
+#endif
#if defined(ENABLE_UV_INTERP)
vec2 uv = uv_interp;
@@ -1658,7 +1658,7 @@ FRAGMENT_SHADER_CODE
normalmap.xy = normalmap.xy * 2.0 - 1.0;
normalmap.z = sqrt(max(0.0, 1.0 - dot(normalmap.xy, normalmap.xy))); //always ignore Z, as it can be RG packed, Z may be pos/neg, etc.
- normal = normalize(mix(normal_interp, tangent * normalmap.x + binormal * normalmap.y + normal * normalmap.z, normaldepth)) * side;
+ normal = normalize(mix(normal, tangent * normalmap.x + binormal * normalmap.y + normal * normalmap.z, normaldepth));
#endif
diff --git a/editor/array_property_edit.cpp b/editor/array_property_edit.cpp
index a32a71262f..245c9273ff 100644
--- a/editor/array_property_edit.cpp
+++ b/editor/array_property_edit.cpp
@@ -30,6 +30,7 @@
#include "array_property_edit.h"
+#include "core/io/marshalls.h"
#include "editor_node.h"
#define ITEMS_PER_PAGE 100
@@ -202,6 +203,11 @@ bool ArrayPropertyEdit::_get(const StringName &p_name, Variant &r_ret) const {
int idx = pn.get_slicec('/', 1).to_int();
bool valid;
r_ret = arr.get(idx, &valid);
+
+ if (r_ret.get_type() == Variant::OBJECT && Object::cast_to<EncodedObjectAsID>(r_ret)) {
+ r_ret = Object::cast_to<EncodedObjectAsID>(r_ret)->get_object_id();
+ }
+
return valid;
}
}
@@ -232,6 +238,11 @@ void ArrayPropertyEdit::_get_property_list(List<PropertyInfo> *p_list) const {
p_list->push_back(PropertyInfo(Variant::INT, "indices/" + itos(i + offset) + "_type", PROPERTY_HINT_ENUM, vtypes));
}
+ if (v.get_type() == Variant::OBJECT && Object::cast_to<EncodedObjectAsID>(v)) {
+ p_list->push_back(PropertyInfo(Variant::INT, "indices/" + itos(i + offset), PROPERTY_HINT_OBJECT_ID, "Object"));
+ continue;
+ }
+
if (is_typed || v.get_type() != Variant::NIL) {
PropertyInfo pi(v.get_type(), "indices/" + itos(i + offset));
if (subtype != Variant::NIL) {
diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp
index 3136b0f012..2a11f70274 100644
--- a/editor/code_editor.cpp
+++ b/editor/code_editor.cpp
@@ -1130,6 +1130,19 @@ void CodeTextEditor::set_edit_state(const Variant &p_state) {
void CodeTextEditor::set_error(const String &p_error) {
error->set_text(p_error);
+ error->set_tooltip(p_error);
+ error->set_visible(p_error != "");
+}
+
+void CodeTextEditor::set_error_pos(int p_line, int p_column) {
+ error_line = p_line;
+ error_column = p_column;
+}
+
+void CodeTextEditor::_error_pressed() {
+ text_editor->cursor_set_line(error_line);
+ text_editor->cursor_set_column(error_column);
+ text_editor->center_viewport_to_cursor();
}
void CodeTextEditor::_update_font() {
@@ -1191,6 +1204,7 @@ void CodeTextEditor::_bind_methods() {
ClassDB::bind_method("_code_complete_timer_timeout", &CodeTextEditor::_code_complete_timer_timeout);
ClassDB::bind_method("_complete_request", &CodeTextEditor::_complete_request);
ClassDB::bind_method("_font_resize_timeout", &CodeTextEditor::_font_resize_timeout);
+ ClassDB::bind_method("_error_pressed", &CodeTextEditor::_error_pressed);
ADD_SIGNAL(MethodInfo("validate_script"));
ADD_SIGNAL(MethodInfo("load_theme_settings"));
@@ -1239,13 +1253,22 @@ CodeTextEditor::CodeTextEditor() {
code_complete_timer->set_wait_time(EDITOR_DEF("text_editor/completion/code_complete_delay", .3f));
- error = memnew(Label);
- status_bar->add_child(error);
- error->set_autowrap(true);
- error->set_valign(Label::VALIGN_CENTER);
+ error_line = 0;
+ error_column = 0;
+
+ Control *error_box = memnew(Control);
+ status_bar->add_child(error_box);
+ error_box->set_v_size_flags(SIZE_EXPAND_FILL);
+ error_box->set_h_size_flags(SIZE_EXPAND_FILL);
+ error_box->set_clip_contents(true);
+
+ error = memnew(LinkButton);
+ error_box->add_child(error);
+ error->set_anchors_and_margins_preset(Control::PRESET_CENTER_LEFT);
+ error->set_underline_mode(LinkButton::UNDERLINE_MODE_ON_HOVER);
error->add_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_color("error_color", "Editor"));
error->add_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_font("status_source", "EditorFonts"));
- error->set_h_size_flags(SIZE_EXPAND_FILL); //required for it to display, given now it's clipping contents, do not touch
+ error->connect("pressed", this, "_error_pressed");
find_replace_bar->connect("error", error, "set_text");
status_bar->add_child(memnew(Label)); //to keep the height if the other labels are not visible
diff --git a/editor/code_editor.h b/editor/code_editor.h
index 2f9403843e..311b6a959b 100644
--- a/editor/code_editor.h
+++ b/editor/code_editor.h
@@ -36,6 +36,7 @@
#include "scene/gui/check_button.h"
#include "scene/gui/dialogs.h"
#include "scene/gui/line_edit.h"
+#include "scene/gui/link_button.h"
#include "scene/gui/text_edit.h"
#include "scene/gui/tool_button.h"
#include "scene/main/timer.h"
@@ -157,7 +158,9 @@ class CodeTextEditor : public VBoxContainer {
int font_resize_val;
real_t font_size;
- Label *error;
+ LinkButton *error;
+ int error_line;
+ int error_column;
void _on_settings_change();
@@ -171,6 +174,7 @@ class CodeTextEditor : public VBoxContainer {
void _zoom_out();
void _zoom_changed();
void _reset_zoom();
+ void _error_pressed();
CodeTextEditorCodeCompleteFunc code_complete_func;
void *code_complete_ud;
@@ -213,6 +217,7 @@ public:
void update_editor_settings();
void set_error(const String &p_error);
+ void set_error_pos(int p_line, int p_column);
void update_line_and_column() { _line_col_changed(); }
TextEdit *get_text_edit() { return text_editor; }
FindReplaceBar *get_find_replace_bar() { return find_replace_bar; }
diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp
index a99c9656ba..94eb1a3399 100644
--- a/editor/editor_file_system.cpp
+++ b/editor/editor_file_system.cpp
@@ -466,6 +466,7 @@ bool EditorFileSystem::_update_scan_actions() {
bool fs_changed = false;
Vector<String> reimports;
+ Vector<String> reloads;
for (List<ItemAction>::Element *E = scan_actions.front(); E; E = E->next()) {
@@ -545,12 +546,25 @@ bool EditorFileSystem::_update_scan_actions() {
fs_changed = true;
} break;
+ case ItemAction::ACTION_FILE_RELOAD: {
+
+ int idx = ia.dir->find_file_index(ia.file);
+ ERR_CONTINUE(idx == -1);
+ String full_path = ia.dir->get_file_path(idx);
+
+ reloads.push_back(full_path);
+
+ } break;
}
}
if (reimports.size()) {
reimport_files(reimports);
}
+
+ if (reloads.size()) {
+ emit_signal("resources_reload", reloads);
+ }
scan_actions.clear();
return fs_changed;
@@ -905,11 +919,11 @@ void EditorFileSystem::_scan_fs_changes(EditorFileSystemDirectory *p_dir, const
continue;
}
+ String path = cd.plus_file(p_dir->files[i]->file);
+
if (import_extensions.has(p_dir->files[i]->file.get_extension().to_lower())) {
//check here if file must be imported or not
- String path = cd.plus_file(p_dir->files[i]->file);
-
uint64_t mt = FileAccess::get_modified_time(path);
bool reimport = false;
@@ -936,6 +950,20 @@ void EditorFileSystem::_scan_fs_changes(EditorFileSystemDirectory *p_dir, const
ia.file = p_dir->files[i]->file;
scan_actions.push_back(ia);
}
+ } else if (ResourceCache::has(path)) { //test for potential reload
+
+ uint64_t mt = FileAccess::get_modified_time(path);
+
+ if (mt != p_dir->files[i]->modified_time) {
+
+ p_dir->files[i]->modified_time = mt; //save new time, but test for reload
+
+ ItemAction ia;
+ ia.action = ItemAction::ACTION_FILE_RELOAD;
+ ia.dir = p_dir;
+ ia.file = p_dir->files[i]->file;
+ scan_actions.push_back(ia);
+ }
}
}
@@ -1726,6 +1754,7 @@ void EditorFileSystem::_bind_methods() {
ADD_SIGNAL(MethodInfo("filesystem_changed"));
ADD_SIGNAL(MethodInfo("sources_changed", PropertyInfo(Variant::BOOL, "exist")));
ADD_SIGNAL(MethodInfo("resources_reimported", PropertyInfo(Variant::POOL_STRING_ARRAY, "resources")));
+ ADD_SIGNAL(MethodInfo("resources_reload", PropertyInfo(Variant::POOL_STRING_ARRAY, "resources")));
}
void EditorFileSystem::_update_extensions() {
diff --git a/editor/editor_file_system.h b/editor/editor_file_system.h
index f6eef2a152..51b3fd38f0 100644
--- a/editor/editor_file_system.h
+++ b/editor/editor_file_system.h
@@ -116,7 +116,8 @@ class EditorFileSystem : public Node {
ACTION_DIR_REMOVE,
ACTION_FILE_ADD,
ACTION_FILE_REMOVE,
- ACTION_FILE_TEST_REIMPORT
+ ACTION_FILE_TEST_REIMPORT,
+ ACTION_FILE_RELOAD
};
Action action;
diff --git a/editor/editor_fonts.cpp b/editor/editor_fonts.cpp
index 8b1818b595..a54ad7894a 100644
--- a/editor/editor_fonts.cpp
+++ b/editor/editor_fonts.cpp
@@ -93,12 +93,14 @@ void editor_register_fonts(Ref<Theme> p_theme) {
/* Custom font */
+ bool font_antialiased = (bool)EditorSettings::get_singleton()->get("interface/editor/main_font_antialiased");
DynamicFontData::Hinting font_hinting = (DynamicFontData::Hinting)(int)EditorSettings::get_singleton()->get("interface/editor/main_font_hinting");
String custom_font_path = EditorSettings::get_singleton()->get("interface/editor/main_font");
Ref<DynamicFontData> CustomFont;
if (custom_font_path.length() > 0 && dir->file_exists(custom_font_path)) {
CustomFont.instance();
+ CustomFont->set_antialiased(font_antialiased);
CustomFont->set_hinting(font_hinting);
CustomFont->set_font_path(custom_font_path);
CustomFont->set_force_autohinter(true); //just looks better..i think?
@@ -112,6 +114,7 @@ void editor_register_fonts(Ref<Theme> p_theme) {
Ref<DynamicFontData> CustomFontBold;
if (custom_font_path_bold.length() > 0 && dir->file_exists(custom_font_path_bold)) {
CustomFontBold.instance();
+ CustomFontBold->set_antialiased(font_antialiased);
CustomFontBold->set_hinting(font_hinting);
CustomFontBold->set_font_path(custom_font_path_bold);
CustomFontBold->set_force_autohinter(true); //just looks better..i think?
@@ -122,10 +125,12 @@ void editor_register_fonts(Ref<Theme> p_theme) {
/* Custom source code font */
String custom_font_path_source = EditorSettings::get_singleton()->get("interface/editor/code_font");
+ bool font_source_antialiased = (bool)EditorSettings::get_singleton()->get("interface/editor/code_font_antialiased");
DynamicFontData::Hinting font_source_hinting = (DynamicFontData::Hinting)(int)EditorSettings::get_singleton()->get("interface/editor/code_font_hinting");
Ref<DynamicFontData> CustomFontSource;
if (custom_font_path_source.length() > 0 && dir->file_exists(custom_font_path_source)) {
CustomFontSource.instance();
+ CustomFontSource->set_antialiased(font_source_antialiased);
CustomFontSource->set_hinting(font_source_hinting);
CustomFontSource->set_font_path(custom_font_path_source);
} else {
@@ -138,48 +143,56 @@ void editor_register_fonts(Ref<Theme> p_theme) {
Ref<DynamicFontData> DefaultFont;
DefaultFont.instance();
+ DefaultFont->set_antialiased(font_antialiased);
DefaultFont->set_hinting(font_hinting);
DefaultFont->set_font_ptr(_font_NotoSansUI_Regular, _font_NotoSansUI_Regular_size);
DefaultFont->set_force_autohinter(true); //just looks better..i think?
Ref<DynamicFontData> DefaultFontBold;
DefaultFontBold.instance();
- DefaultFont->set_hinting(font_hinting);
+ DefaultFontBold->set_antialiased(font_antialiased);
+ DefaultFontBold->set_hinting(font_hinting);
DefaultFontBold->set_font_ptr(_font_NotoSansUI_Bold, _font_NotoSansUI_Bold_size);
DefaultFontBold->set_force_autohinter(true); // just looks better..i think?
Ref<DynamicFontData> FontFallback;
FontFallback.instance();
+ FontFallback->set_antialiased(font_antialiased);
FontFallback->set_hinting(font_hinting);
FontFallback->set_font_ptr(_font_DroidSansFallback, _font_DroidSansFallback_size);
FontFallback->set_force_autohinter(true); //just looks better..i think?
Ref<DynamicFontData> FontJapanese;
FontJapanese.instance();
+ FontJapanese->set_antialiased(font_antialiased);
FontJapanese->set_hinting(font_hinting);
FontJapanese->set_font_ptr(_font_DroidSansJapanese, _font_DroidSansJapanese_size);
FontJapanese->set_force_autohinter(true); //just looks better..i think?
Ref<DynamicFontData> FontArabic;
FontArabic.instance();
+ FontArabic->set_antialiased(font_antialiased);
FontArabic->set_hinting(font_hinting);
FontArabic->set_font_ptr(_font_NotoNaskhArabicUI_Regular, _font_NotoNaskhArabicUI_Regular_size);
FontArabic->set_force_autohinter(true); //just looks better..i think?
Ref<DynamicFontData> FontHebrew;
FontHebrew.instance();
+ FontHebrew->set_antialiased(font_antialiased);
FontHebrew->set_hinting(font_hinting);
FontHebrew->set_font_ptr(_font_NotoSansHebrew_Regular, _font_NotoSansHebrew_Regular_size);
FontHebrew->set_force_autohinter(true); //just looks better..i think?
Ref<DynamicFontData> FontThai;
FontThai.instance();
+ FontThai->set_antialiased(font_antialiased);
FontThai->set_hinting(font_hinting);
FontThai->set_font_ptr(_font_NotoSansThaiUI_Regular, _font_NotoSansThaiUI_Regular_size);
FontThai->set_force_autohinter(true); //just looks better..i think?
Ref<DynamicFontData> FontHindi;
FontHindi.instance();
+ FontHindi->set_antialiased(font_antialiased);
FontHindi->set_hinting(font_hinting);
FontHindi->set_font_ptr(_font_NotoSansDevanagariUI_Regular, _font_NotoSansDevanagariUI_Regular_size);
FontHindi->set_force_autohinter(true); //just looks better..i think?
@@ -188,6 +201,7 @@ void editor_register_fonts(Ref<Theme> p_theme) {
Ref<DynamicFontData> dfmono;
dfmono.instance();
+ dfmono->set_antialiased(font_source_antialiased);
dfmono->set_hinting(font_source_hinting);
dfmono->set_font_ptr(_font_Hack_Regular, _font_Hack_Regular_size);
//dfd->set_force_autohinter(true); //just looks better..i think?
diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp
index de1f856608..f502f918df 100644
--- a/editor/editor_help.cpp
+++ b/editor/editor_help.cpp
@@ -40,482 +40,6 @@
#define CONTRIBUTE2_URL "https://github.com/godotengine/godot-docs"
#define REQUEST_URL "https://github.com/godotengine/godot-docs/issues/new"
-void EditorHelpSearch::popup_dialog() {
-
- popup_centered(Size2(700, 600) * EDSCALE);
- if (search_box->get_text() != "") {
- search_box->select_all();
- _update_search();
- }
- search_box->grab_focus();
-}
-
-void EditorHelpSearch::popup_dialog(const String &p_term) {
-
- popup_centered(Size2(700, 600) * EDSCALE);
- if (p_term != "") {
- search_box->set_text(p_term);
- search_box->select_all();
- _update_search();
- } else {
- search_box->clear();
- }
- search_box->grab_focus();
-}
-
-void EditorHelpSearch::_text_changed(const String &p_newtext) {
-
- _update_search();
-}
-
-void EditorHelpSearch::_sbox_input(const Ref<InputEvent> &p_ie) {
-
- Ref<InputEventKey> k = p_ie;
-
- if (k.is_valid() && (k->get_scancode() == KEY_UP ||
- k->get_scancode() == KEY_DOWN ||
- k->get_scancode() == KEY_PAGEUP ||
- k->get_scancode() == KEY_PAGEDOWN)) {
-
- search_options->call("_gui_input", k);
- search_box->accept_event();
- }
-}
-
-void EditorHelpSearch::IncrementalSearch::phase1(Map<String, DocData::ClassDoc>::Element *E) {
-
- if (E->key().findn(term) != -1) {
-
- TreeItem *item = search_options->create_item(root);
- item->set_metadata(0, "class_name:" + E->key());
- item->set_text(0, E->key() + " (Class)");
- Ref<Texture> icon = EditorNode::get_singleton()->get_class_icon(E->key(), "Node");
- item->set_icon(0, icon);
- }
-}
-
-void EditorHelpSearch::IncrementalSearch::phase2(Map<String, DocData::ClassDoc>::Element *E) {
-
- DocData::ClassDoc &c = E->get();
-
- Ref<Texture> cicon = EditorNode::get_singleton()->get_class_icon(E->key(), "Node");
-
- for (int i = 0; i < c.methods.size(); i++) {
- if ((term.begins_with(".") && c.methods[i].name.begins_with(term.right(1))) || (term.ends_with("(") && c.methods[i].name.ends_with(term.left(term.length() - 1).strip_edges())) || (term.begins_with(".") && term.ends_with("(") && c.methods[i].name == term.substr(1, term.length() - 2).strip_edges()) || c.methods[i].name.findn(term) != -1) {
-
- TreeItem *item = search_options->create_item(root);
- item->set_metadata(0, "class_method:" + E->key() + ":" + c.methods[i].name);
- item->set_text(0, E->key() + "." + c.methods[i].name + " (Method)");
- item->set_icon(0, cicon);
- }
- }
-
- for (int i = 0; i < c.signals.size(); i++) {
-
- if (c.signals[i].name.findn(term) != -1) {
-
- TreeItem *item = search_options->create_item(root);
- item->set_metadata(0, "class_signal:" + E->key() + ":" + c.signals[i].name);
- item->set_text(0, E->key() + "." + c.signals[i].name + " (Signal)");
- item->set_icon(0, cicon);
- }
- }
-
- for (int i = 0; i < c.constants.size(); i++) {
-
- if (c.constants[i].name.findn(term) != -1) {
-
- TreeItem *item = search_options->create_item(root);
- item->set_metadata(0, "class_constant:" + E->key() + ":" + c.constants[i].name);
- item->set_text(0, E->key() + "." + c.constants[i].name + " (Constant)");
- item->set_icon(0, cicon);
- }
- }
-
- for (int i = 0; i < c.properties.size(); i++) {
-
- if (c.properties[i].name.findn(term) != -1) {
-
- TreeItem *item = search_options->create_item(root);
- item->set_metadata(0, "class_property:" + E->key() + ":" + c.properties[i].name);
- item->set_text(0, E->key() + "." + c.properties[i].name + " (Property)");
- item->set_icon(0, cicon);
- }
- }
-
- for (int i = 0; i < c.theme_properties.size(); i++) {
-
- if (c.theme_properties[i].name.findn(term) != -1) {
-
- TreeItem *item = search_options->create_item(root);
- item->set_metadata(0, "class_theme_item:" + E->key() + ":" + c.theme_properties[i].name);
- item->set_text(0, E->key() + "." + c.theme_properties[i].name + " (Theme Item)");
- item->set_icon(0, cicon);
- }
- }
-}
-
-bool EditorHelpSearch::IncrementalSearch::slice() {
-
- if (phase > 2)
- return true;
-
- if (iterator) {
-
- switch (phase) {
-
- case 1: {
- phase1(iterator);
- } break;
- case 2: {
- phase2(iterator);
- } break;
- default: {
- WARN_PRINT("illegal phase in IncrementalSearch");
- return true;
- }
- }
-
- iterator = iterator->next();
- } else {
-
- phase += 1;
- iterator = doc->class_list.front();
- }
-
- return false;
-}
-
-EditorHelpSearch::IncrementalSearch::IncrementalSearch(EditorHelpSearch *p_search, Tree *p_search_options, const String &p_term) :
- search(p_search),
- search_options(p_search_options) {
-
- def_icon = search->get_icon("Node", "EditorIcons");
- doc = EditorHelp::get_doc_data();
-
- term = p_term;
-
- root = search_options->create_item();
- phase = 0;
- iterator = 0;
-}
-
-bool EditorHelpSearch::IncrementalSearch::empty() const {
-
- return root->get_children() == NULL;
-}
-
-bool EditorHelpSearch::IncrementalSearch::work(uint64_t slot) {
-
- const uint64_t until = OS::get_singleton()->get_ticks_usec() + slot;
-
- while (!slice()) {
-
- if (OS::get_singleton()->get_ticks_usec() > until)
- return false;
- }
-
- return true;
-}
-
-void EditorHelpSearch::_update_search() {
- search_options->clear();
-
- String term = search_box->get_text();
- if (term.length() < 2)
- return;
-
- search = Ref<IncrementalSearch>(memnew(IncrementalSearch(this, search_options, term)));
- set_process(true);
-}
-
-void EditorHelpSearch::_confirmed() {
-
- TreeItem *ti = search_options->get_selected();
- if (!ti)
- return;
-
- String mdata = ti->get_metadata(0);
- EditorNode::get_singleton()->set_visible_editor(EditorNode::EDITOR_SCRIPT);
- emit_signal("go_to_help", mdata);
- // go to that
- hide();
-}
-
-void EditorHelpSearch::_notification(int p_what) {
-
- if (p_what == NOTIFICATION_ENTER_TREE) {
-
- //_update_icons
- search_box->set_right_icon(get_icon("Search", "EditorIcons"));
- search_box->set_clear_button_enabled(true);
-
- connect("confirmed", this, "_confirmed");
- _update_search();
- } else if (p_what == NOTIFICATION_EXIT_TREE) {
- disconnect("confirmed", this, "_confirmed");
- } else if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {
-
- if (is_visible_in_tree()) {
-
- search_box->call_deferred("grab_focus"); // still not visible
- search_box->select_all();
- }
- } else if (p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) {
-
- //_update_icons
- search_box->set_right_icon(get_icon("Search", "EditorIcons"));
- search_box->set_clear_button_enabled(true);
- } else if (p_what == NOTIFICATION_PROCESS) {
-
- if (search.is_valid()) {
-
- if (search->work()) {
-
- get_ok()->set_disabled(search->empty());
- search = Ref<IncrementalSearch>();
- set_process(false);
- }
- } else {
-
- set_process(false);
- }
- }
-}
-
-void EditorHelpSearch::_bind_methods() {
-
- ClassDB::bind_method(D_METHOD("_text_changed"), &EditorHelpSearch::_text_changed);
- ClassDB::bind_method(D_METHOD("_confirmed"), &EditorHelpSearch::_confirmed);
- ClassDB::bind_method(D_METHOD("_sbox_input"), &EditorHelpSearch::_sbox_input);
- ClassDB::bind_method(D_METHOD("_update_search"), &EditorHelpSearch::_update_search);
-
- ADD_SIGNAL(MethodInfo("go_to_help"));
-}
-
-EditorHelpSearch::EditorHelpSearch() {
-
- VBoxContainer *vbc = memnew(VBoxContainer);
- add_child(vbc);
-
- search_box = memnew(LineEdit);
- vbc->add_child(search_box);
- search_box->connect("text_changed", this, "_text_changed");
- search_box->connect("gui_input", this, "_sbox_input");
- search_options = memnew(Tree);
- search_options->set_hide_root(true);
- vbc->add_margin_child(TTR("Matches:"), search_options, true);
- get_ok()->set_text(TTR("Open"));
- get_ok()->set_disabled(true);
- register_text_enter(search_box);
- set_hide_on_ok(false);
- search_options->connect("item_activated", this, "_confirmed");
- set_title(TTR("Search Help"));
-}
-
-/////////////////////////////////
-
-void EditorHelpIndex::add_type(const String &p_type, HashMap<String, TreeItem *> &p_types, TreeItem *p_root) {
-
- if (p_types.has(p_type))
- return;
-
- String inherits = EditorHelp::get_doc_data()->class_list[p_type].inherits;
-
- TreeItem *parent = p_root;
-
- if (inherits.length()) {
-
- if (!p_types.has(inherits)) {
-
- add_type(inherits, p_types, p_root);
- }
-
- if (p_types.has(inherits))
- parent = p_types[inherits];
- }
-
- TreeItem *item = class_list->create_item(parent);
- item->set_metadata(0, p_type);
- item->set_tooltip(0, EditorHelp::get_doc_data()->class_list[p_type].brief_description);
- item->set_text(0, p_type);
-
- Ref<Texture> icon = EditorNode::get_singleton()->get_class_icon(p_type);
- item->set_icon(0, icon);
-
- p_types[p_type] = item;
-}
-
-void EditorHelpIndex::_tree_item_selected() {
-
- TreeItem *s = class_list->get_selected();
- if (!s)
- return;
-
- EditorNode::get_singleton()->set_visible_editor(EditorNode::EDITOR_SCRIPT);
- emit_signal("open_class", s->get_text(0));
- hide();
-}
-
-void EditorHelpIndex::select_class(const String &p_class) {
-
- if (!tree_item_map.has(p_class))
- return;
- tree_item_map[p_class]->select(0);
- class_list->ensure_cursor_is_visible();
-}
-
-void EditorHelpIndex::popup_dialog() {
-
- popup_centered(Size2(500, 600) * EDSCALE);
-
- search_box->set_text("");
- _update_class_list();
-}
-
-void EditorHelpIndex::_notification(int p_what) {
-
- if (p_what == NOTIFICATION_ENTER_TREE) {
-
- //_update_icons
- search_box->set_right_icon(get_icon("Search", "EditorIcons"));
- search_box->set_clear_button_enabled(true);
- _update_class_list();
-
- connect("confirmed", this, "_tree_item_selected");
-
- } else if (p_what == NOTIFICATION_POST_POPUP) {
-
- search_box->call_deferred("grab_focus");
- } else if (p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) {
-
- //_update_icons
- search_box->set_right_icon(get_icon("Search", "EditorIcons"));
- search_box->set_clear_button_enabled(true);
-
- bool enable_rl = EditorSettings::get_singleton()->get("docks/scene_tree/draw_relationship_lines");
- Color rl_color = EditorSettings::get_singleton()->get("docks/scene_tree/relationship_line_color");
-
- if (enable_rl) {
- class_list->add_constant_override("draw_relationship_lines", 1);
- class_list->add_color_override("relationship_line_color", rl_color);
- class_list->add_constant_override("draw_guides", 0);
- } else {
- class_list->add_constant_override("draw_relationship_lines", 0);
- class_list->add_constant_override("draw_guides", 1);
- }
- }
-}
-
-void EditorHelpIndex::_text_changed(const String &p_text) {
-
- _update_class_list();
-}
-
-void EditorHelpIndex::_update_class_list() {
-
- class_list->clear();
- tree_item_map.clear();
- TreeItem *root = class_list->create_item();
-
- String filter = search_box->get_text().strip_edges();
- String to_select = "";
-
- for (Map<String, DocData::ClassDoc>::Element *E = EditorHelp::get_doc_data()->class_list.front(); E; E = E->next()) {
-
- if (filter == "") {
- add_type(E->key(), tree_item_map, root);
- } else {
-
- bool found = false;
- String type = E->key();
-
- while (type != "") {
- if (filter.is_subsequence_ofi(type)) {
-
- if (to_select.empty() || type.length() < to_select.length()) {
- to_select = type;
- }
-
- found = true;
- }
-
- type = EditorHelp::get_doc_data()->class_list[type].inherits;
- }
-
- if (found) {
- add_type(E->key(), tree_item_map, root);
- }
- }
- }
-
- if (tree_item_map.has(filter)) {
- select_class(filter);
- } else if (to_select != "") {
- select_class(to_select);
- }
-}
-
-void EditorHelpIndex::_sbox_input(const Ref<InputEvent> &p_ie) {
-
- Ref<InputEventKey> k = p_ie;
-
- if (k.is_valid() && (k->get_scancode() == KEY_UP ||
- k->get_scancode() == KEY_DOWN ||
- k->get_scancode() == KEY_PAGEUP ||
- k->get_scancode() == KEY_PAGEDOWN)) {
-
- class_list->call("_gui_input", k);
- search_box->accept_event();
- }
-}
-
-void EditorHelpIndex::_bind_methods() {
-
- ClassDB::bind_method("_tree_item_selected", &EditorHelpIndex::_tree_item_selected);
- ClassDB::bind_method("_text_changed", &EditorHelpIndex::_text_changed);
- ClassDB::bind_method("_sbox_input", &EditorHelpIndex::_sbox_input);
- ClassDB::bind_method("select_class", &EditorHelpIndex::select_class);
- ADD_SIGNAL(MethodInfo("open_class"));
-}
-
-EditorHelpIndex::EditorHelpIndex() {
-
- VBoxContainer *vbc = memnew(VBoxContainer);
- add_child(vbc);
-
- search_box = memnew(LineEdit);
- vbc->add_child(search_box);
- search_box->set_h_size_flags(SIZE_EXPAND_FILL);
-
- register_text_enter(search_box);
-
- search_box->connect("text_changed", this, "_text_changed");
- search_box->connect("gui_input", this, "_sbox_input");
-
- class_list = memnew(Tree);
- vbc->add_margin_child(TTR("Class List:") + " ", class_list, true);
- class_list->set_hide_root(true);
- class_list->set_v_size_flags(SIZE_EXPAND_FILL);
-
- class_list->connect("item_activated", this, "_tree_item_selected");
-
- bool enable_rl = EditorSettings::get_singleton()->get("docks/scene_tree/draw_relationship_lines");
- Color rl_color = EditorSettings::get_singleton()->get("docks/scene_tree/relationship_line_color");
-
- if (enable_rl) {
- class_list->add_constant_override("draw_relationship_lines", 1);
- class_list->add_color_override("relationship_line_color", rl_color);
- } else {
- class_list->add_constant_override("draw_relationship_lines", 0);
- }
-
- get_ok()->set_text(TTR("Open"));
- set_title(TTR("Search Classes"));
-}
-
-/////////////////////////////////
-
DocData *EditorHelp::doc = NULL;
void EditorHelp::_init_colors() {
@@ -1923,8 +1447,6 @@ EditorHelp::EditorHelp() {
EditorHelp::~EditorHelp() {
}
-/////////////
-
void EditorHelpBit::_go_to_help(String p_what) {
EditorNode::get_singleton()->set_visible_editor(EditorNode::EDITOR_SCRIPT);
diff --git a/editor/editor_help.h b/editor/editor_help.h
index 25db68b42d..205778ec11 100644
--- a/editor/editor_help.h
+++ b/editor/editor_help.h
@@ -31,6 +31,8 @@
#ifndef EDITOR_HELP_H
#define EDITOR_HELP_H
+#include "editor/code_editor.h"
+#include "editor/doc/doc_data.h"
#include "editor/editor_plugin.h"
#include "scene/gui/menu_button.h"
#include "scene/gui/panel_container.h"
@@ -38,95 +40,9 @@
#include "scene/gui/split_container.h"
#include "scene/gui/tab_container.h"
#include "scene/gui/text_edit.h"
-#include "scene/gui/tree.h"
-
-#include "editor/code_editor.h"
-#include "editor/doc/doc_data.h"
#include "scene/main/timer.h"
-class EditorNode;
-
-class EditorHelpSearch : public ConfirmationDialog {
-
- GDCLASS(EditorHelpSearch, ConfirmationDialog)
-
- LineEdit *search_box;
- Tree *search_options;
- String base_type;
-
- class IncrementalSearch : public Reference {
- String term;
- TreeItem *root;
-
- EditorHelpSearch *search;
- Tree *search_options;
-
- DocData *doc;
- Ref<Texture> def_icon;
-
- int phase;
- Map<String, DocData::ClassDoc>::Element *iterator;
-
- void phase1(Map<String, DocData::ClassDoc>::Element *E);
- void phase2(Map<String, DocData::ClassDoc>::Element *E);
- bool slice();
-
- public:
- IncrementalSearch(EditorHelpSearch *p_search, Tree *p_search_options, const String &p_term);
-
- bool empty() const;
- bool work(uint64_t slot = 1000000 / 10);
- };
-
- Ref<IncrementalSearch> search;
-
- void _update_search();
-
- void _sbox_input(const Ref<InputEvent> &p_ie);
-
- void _confirmed();
- void _text_changed(const String &p_newtext);
-
-protected:
- void _notification(int p_what);
- static void _bind_methods();
-
-public:
- void popup_dialog();
- void popup_dialog(const String &p_term);
-
- EditorHelpSearch();
-};
-
-class EditorHelpIndex : public ConfirmationDialog {
- GDCLASS(EditorHelpIndex, ConfirmationDialog);
-
- LineEdit *search_box;
- Tree *class_list;
- HashMap<String, TreeItem *> tree_item_map;
-
- void _tree_item_selected();
- void _text_changed(const String &p_text);
- void _sbox_input(const Ref<InputEvent> &p_ie);
-
- void _update_class_list();
-
- void add_type(const String &p_type, HashMap<String, TreeItem *> &p_types, TreeItem *p_root);
-
-protected:
- void _notification(int p_what);
- static void _bind_methods();
-
-public:
- void select_class(const String &p_class);
-
- void popup_dialog();
-
- EditorHelpIndex();
-};
-
class FindBar : public HBoxContainer {
-
GDCLASS(FindBar, HBoxContainer);
LineEdit *search_text;
@@ -172,6 +88,7 @@ public:
};
class EditorHelp : public VBoxContainer {
+
GDCLASS(EditorHelp, VBoxContainer);
enum Page {
diff --git a/editor/editor_help_search.cpp b/editor/editor_help_search.cpp
new file mode 100644
index 0000000000..55d28871c8
--- /dev/null
+++ b/editor/editor_help_search.cpp
@@ -0,0 +1,597 @@
+/*************************************************************************/
+/* editor_help_search.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "editor_help_search.h"
+
+#include "core/os/keyboard.h"
+#include "editor_node.h"
+
+void EditorHelpSearch::_update_icons() {
+
+ search_box->set_right_icon(get_icon("Search", "EditorIcons"));
+ search_box->set_clear_button_enabled(true);
+ search_box->add_icon_override("right_icon", get_icon("Search", "EditorIcons"));
+ case_sensitive_button->set_icon(get_icon("MatchCase", "EditorIcons"));
+ hierarchy_button->set_icon(get_icon("ClassList", "EditorIcons"));
+
+ if (is_visible_in_tree())
+ _update_results();
+}
+
+void EditorHelpSearch::_load_settings() {
+
+ bool enable_rl = EditorSettings::get_singleton()->get("docks/scene_tree/draw_relationship_lines");
+ Color rl_color = EditorSettings::get_singleton()->get("docks/scene_tree/relationship_line_color");
+
+ if (enable_rl) {
+ results_tree->add_constant_override("draw_relationship_lines", 1);
+ results_tree->add_color_override("relationship_line_color", rl_color);
+ results_tree->add_constant_override("draw_guides", 0);
+ } else {
+ results_tree->add_constant_override("draw_relationship_lines", 0);
+ results_tree->add_constant_override("draw_guides", 1);
+ }
+}
+
+void EditorHelpSearch::_update_results() {
+
+ String term = search_box->get_text();
+
+ int search_flags = filter_combo->get_selected_id();
+ if (case_sensitive_button->is_pressed())
+ search_flags |= SEARCH_CASE_SENSITIVE;
+ if (hierarchy_button->is_pressed())
+ search_flags |= SEARCH_SHOW_HIERARCHY;
+
+ search = Ref<Runner>(memnew(Runner(this, results_tree, term, search_flags)));
+ set_process(true);
+}
+
+void EditorHelpSearch::_search_box_gui_input(const Ref<InputEvent> &p_ie) {
+
+ // Redirect up and down navigational key events to the results list.
+ Ref<InputEventKey> k = p_ie;
+ if (k.is_valid()) {
+ switch (k->get_scancode()) {
+ case KEY_UP:
+ case KEY_DOWN:
+ case KEY_PAGEUP:
+ case KEY_PAGEDOWN: {
+ results_tree->call("_gui_input", k);
+ search_box->accept_event();
+ } break;
+ }
+ }
+}
+
+void EditorHelpSearch::_search_box_text_changed(const String &p_text) {
+
+ _update_results();
+}
+
+void EditorHelpSearch::_case_sensitive_button_pressed() {
+
+ search_box->grab_focus();
+ _update_results();
+}
+
+void EditorHelpSearch::_hierarchy_button_pressed() {
+
+ search_box->grab_focus();
+ _update_results();
+}
+
+void EditorHelpSearch::_filter_combo_item_selected(int p_option) {
+
+ _update_results();
+}
+
+void EditorHelpSearch::_confirmed() {
+
+ TreeItem *item = results_tree->get_selected();
+ if (!item)
+ return;
+
+ // Activate the script editor and emit the signal with the documentation link to display.
+ EditorNode::get_singleton()->set_visible_editor(EditorNode::EDITOR_SCRIPT);
+
+ emit_signal("go_to_help", item->get_metadata(0));
+
+ hide();
+}
+
+void EditorHelpSearch::_notification(int p_what) {
+
+ switch (p_what) {
+ case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
+
+ _load_settings();
+ _update_icons();
+ } break;
+ case NOTIFICATION_ENTER_TREE: {
+
+ connect("confirmed", this, "_confirmed");
+ _update_icons();
+ } break;
+ case NOTIFICATION_POPUP_HIDE: {
+
+ results_tree->clear();
+ get_ok()->set_disabled(true);
+ EditorSettings::get_singleton()->set("interface/dialogs/search_help_bounds", get_rect());
+ } break;
+ case NOTIFICATION_PROCESS: {
+
+ // Update background search.
+ if (search.is_valid()) {
+ if (search->work()) {
+ // Search done.
+ get_ok()->set_disabled(!results_tree->get_selected());
+ search = Ref<Runner>();
+ set_process(false);
+ }
+ } else {
+ set_process(false);
+ }
+ } break;
+ }
+}
+
+void EditorHelpSearch::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("_search_box_gui_input"), &EditorHelpSearch::_search_box_gui_input);
+ ClassDB::bind_method(D_METHOD("_search_box_text_changed"), &EditorHelpSearch::_search_box_text_changed);
+ ClassDB::bind_method(D_METHOD("_case_sensitive_button_pressed"), &EditorHelpSearch::_case_sensitive_button_pressed);
+ ClassDB::bind_method(D_METHOD("_hierarchy_button_pressed"), &EditorHelpSearch::_hierarchy_button_pressed);
+ ClassDB::bind_method(D_METHOD("_filter_combo_item_selected"), &EditorHelpSearch::_filter_combo_item_selected);
+ ClassDB::bind_method(D_METHOD("_confirmed"), &EditorHelpSearch::_confirmed);
+ ADD_SIGNAL(MethodInfo("go_to_help"));
+}
+
+void EditorHelpSearch::popup_dialog() {
+
+ popup_dialog(search_box->get_text());
+}
+
+void EditorHelpSearch::popup_dialog(const String &p_term) {
+
+ // Restore valid window bounds or pop up at default size.
+ if (EditorSettings::get_singleton()->has_setting("interface/dialogs/search_help_bounds"))
+ popup(EditorSettings::get_singleton()->get("interface/dialogs/search_help_bounds"));
+ else
+ popup_centered_ratio(0.5F);
+
+ if (p_term == "") {
+ search_box->clear();
+ } else {
+ search_box->set_text(p_term);
+ search_box->select_all();
+ }
+ search_box->grab_focus();
+ _update_results();
+}
+
+EditorHelpSearch::EditorHelpSearch() {
+
+ set_hide_on_ok(false);
+ set_resizable(true);
+ set_title(TTR("Search Help"));
+
+ get_ok()->set_disabled(true);
+ get_ok()->set_text(TTR("Open"));
+
+ // Split search and results area.
+ VBoxContainer *vbox = memnew(VBoxContainer);
+ add_child(vbox);
+
+ // Create the search box and filter controls (at the top).
+ HBoxContainer *hbox = memnew(HBoxContainer);
+ vbox->add_child(hbox);
+
+ search_box = memnew(LineEdit);
+ search_box->set_custom_minimum_size(Size2(200, 0));
+ search_box->set_h_size_flags(SIZE_EXPAND_FILL);
+ search_box->connect("gui_input", this, "_search_box_gui_input");
+ search_box->connect("text_changed", this, "_search_box_text_changed");
+ register_text_enter(search_box);
+ hbox->add_child(search_box);
+
+ case_sensitive_button = memnew(ToolButton);
+ case_sensitive_button->set_tooltip("Case Sensitive");
+ case_sensitive_button->connect("pressed", this, "_case_sensitive_button_pressed");
+ case_sensitive_button->set_toggle_mode(true);
+ hbox->add_child(case_sensitive_button);
+
+ hierarchy_button = memnew(ToolButton);
+ hierarchy_button->set_tooltip("Show Hierarchy");
+ hierarchy_button->connect("pressed", this, "_hierarchy_button_pressed");
+ hierarchy_button->set_toggle_mode(true);
+ hierarchy_button->set_pressed(true);
+ hbox->add_child(hierarchy_button);
+
+ filter_combo = memnew(OptionButton);
+ filter_combo->set_custom_minimum_size(Size2(200, 0));
+ filter_combo->set_stretch_ratio(0); // Fixed width.
+ filter_combo->add_item(TTR("Display All"), SEARCH_ALL);
+ filter_combo->add_separator();
+ filter_combo->add_item(TTR("Classes Only"), SEARCH_CLASSES);
+ filter_combo->add_item(TTR("Methods Only"), SEARCH_METHODS);
+ filter_combo->add_item(TTR("Signals Only"), SEARCH_SIGNALS);
+ filter_combo->add_item(TTR("Constants Only"), SEARCH_CONSTANTS);
+ filter_combo->add_item(TTR("Properties Only"), SEARCH_PROPERTIES);
+ filter_combo->add_item(TTR("Theme Properties Only"), SEARCH_THEME_ITEMS);
+ filter_combo->connect("item_selected", this, "_filter_combo_item_selected");
+ hbox->add_child(filter_combo);
+
+ // Create the results tree.
+ results_tree = memnew(Tree);
+ results_tree->set_v_size_flags(SIZE_EXPAND_FILL);
+ results_tree->set_columns(2);
+ results_tree->set_column_title(0, TTR("Name"));
+ results_tree->set_column_title(1, TTR("Member Type"));
+ results_tree->set_column_expand(1, false);
+ results_tree->set_column_min_width(1, 150);
+ results_tree->set_custom_minimum_size(Size2(0, 100));
+ results_tree->set_hide_root(true);
+ results_tree->set_select_mode(Tree::SELECT_ROW);
+ results_tree->connect("item_activated", this, "_confirmed");
+ results_tree->connect("item_selected", get_ok(), "set_disabled", varray(false));
+ vbox->add_child(results_tree, true);
+
+ _load_settings();
+}
+
+bool EditorHelpSearch::Runner::_slice() {
+
+ bool phase_done = false;
+ switch (phase) {
+ case PHASE_MATCH_CLASSES_INIT:
+ phase_done = _phase_match_classes_init();
+ break;
+ case PHASE_MATCH_CLASSES:
+ phase_done = _phase_match_classes();
+ break;
+ case PHASE_CLASS_ITEMS_INIT:
+ phase_done = _phase_class_items_init();
+ break;
+ case PHASE_CLASS_ITEMS:
+ phase_done = _phase_class_items();
+ break;
+ case PHASE_MEMBER_ITEMS_INIT:
+ phase_done = _phase_member_items_init();
+ break;
+ case PHASE_MEMBER_ITEMS:
+ phase_done = _phase_member_items();
+ break;
+ case PHASE_SELECT_MATCH:
+ phase_done = _phase_select_match();
+ break;
+ case PHASE_MAX:
+ return true;
+ default:
+ WARN_PRINTS("Invalid or unhandled phase in EditorHelpSearch::Runner, aborting search.");
+ return true;
+ };
+
+ if (phase_done)
+ phase++;
+ return false;
+}
+
+bool EditorHelpSearch::Runner::_phase_match_classes_init() {
+
+ iterator_doc = EditorHelp::get_doc_data()->class_list.front();
+ matches.clear();
+ matched_item = NULL;
+
+ return true;
+}
+
+bool EditorHelpSearch::Runner::_phase_match_classes() {
+
+ DocData::ClassDoc &class_doc = iterator_doc->value();
+
+ matches[class_doc.name] = ClassMatch();
+ ClassMatch &match = matches[class_doc.name];
+
+ match.doc = &class_doc;
+
+ // Match class name.
+ if (search_flags & SEARCH_CLASSES)
+ match.name = term == "" || _match_string(term, class_doc.name);
+
+ // Match members if the term is long enough.
+ if (term.length() > 1) {
+ if (search_flags & SEARCH_METHODS)
+ for (int i = 0; i < class_doc.methods.size(); i++) {
+ String method_name = search_flags & SEARCH_CASE_SENSITIVE ? class_doc.methods[i].name : class_doc.methods[i].name.to_lower();
+ if (method_name.find(term) > -1 ||
+ (term.begins_with(".") && method_name.begins_with(term.right(1))) ||
+ (term.ends_with("(") && method_name.ends_with(term.left(term.length() - 1).strip_edges())) ||
+ (term.begins_with(".") && term.ends_with("(") && method_name == term.substr(1, term.length() - 2).strip_edges()))
+ match.methods.push_back(const_cast<DocData::MethodDoc *>(&class_doc.methods[i]));
+ }
+ if (search_flags & SEARCH_SIGNALS)
+ for (int i = 0; i < class_doc.signals.size(); i++)
+ if (_match_string(term, class_doc.signals[i].name))
+ match.signals.push_back(const_cast<DocData::MethodDoc *>(&class_doc.signals[i]));
+ if (search_flags & SEARCH_CONSTANTS)
+ for (int i = 0; i < class_doc.constants.size(); i++)
+ if (_match_string(term, class_doc.constants[i].name))
+ match.constants.push_back(const_cast<DocData::ConstantDoc *>(&class_doc.constants[i]));
+ if (search_flags & SEARCH_PROPERTIES)
+ for (int i = 0; i < class_doc.properties.size(); i++)
+ if (_match_string(term, class_doc.properties[i].name))
+ match.properties.push_back(const_cast<DocData::PropertyDoc *>(&class_doc.properties[i]));
+ if (search_flags & SEARCH_THEME_ITEMS)
+ for (int i = 0; i < class_doc.theme_properties.size(); i++)
+ if (_match_string(term, class_doc.theme_properties[i].name))
+ match.theme_properties.push_back(const_cast<DocData::PropertyDoc *>(&class_doc.theme_properties[i]));
+ }
+
+ iterator_doc = iterator_doc->next();
+ return !iterator_doc;
+}
+
+bool EditorHelpSearch::Runner::_phase_class_items_init() {
+
+ iterator_match = matches.front();
+
+ results_tree->clear();
+ root_item = results_tree->create_item();
+ class_items.clear();
+
+ return true;
+}
+
+bool EditorHelpSearch::Runner::_phase_class_items() {
+
+ ClassMatch &match = iterator_match->value();
+
+ if (search_flags & SEARCH_SHOW_HIERARCHY) {
+ if (match.required())
+ _create_class_hierarchy(match);
+ } else {
+ if (match.name)
+ _create_class_item(root_item, match.doc, false);
+ }
+
+ iterator_match = iterator_match->next();
+ return !iterator_match;
+}
+
+bool EditorHelpSearch::Runner::_phase_member_items_init() {
+
+ iterator_match = matches.front();
+
+ return true;
+}
+
+bool EditorHelpSearch::Runner::_phase_member_items() {
+
+ ClassMatch &match = iterator_match->value();
+
+ TreeItem *parent = search_flags & SEARCH_SHOW_HIERARCHY ? class_items[match.doc->name] : root_item;
+ for (int i = 0; i < match.methods.size(); i++)
+ _create_method_item(parent, match.doc, match.methods[i]);
+ for (int i = 0; i < match.signals.size(); i++)
+ _create_signal_item(parent, match.doc, match.signals[i]);
+ for (int i = 0; i < match.constants.size(); i++)
+ _create_constant_item(parent, match.doc, match.constants[i]);
+ for (int i = 0; i < match.properties.size(); i++)
+ _create_property_item(parent, match.doc, match.properties[i]);
+ for (int i = 0; i < match.theme_properties.size(); i++)
+ _create_theme_property_item(parent, match.doc, match.theme_properties[i]);
+
+ iterator_match = iterator_match->next();
+ return !iterator_match;
+}
+
+bool EditorHelpSearch::Runner::_phase_select_match() {
+
+ if (matched_item)
+ matched_item->select(0);
+ results_tree->ensure_cursor_is_visible();
+
+ return true;
+}
+
+bool EditorHelpSearch::Runner::_match_string(const String &p_term, const String &p_string) const {
+
+ if (search_flags & SEARCH_CASE_SENSITIVE)
+ return p_string.find(p_term) > -1;
+ else
+ return p_string.findn(p_term) > -1;
+}
+
+void EditorHelpSearch::Runner::_match_item(TreeItem *p_item, const String &p_text) {
+
+ if (!matched_item) {
+ if (search_flags & SEARCH_CASE_SENSITIVE) {
+ if (p_text.casecmp_to(term) == 0)
+ matched_item = p_item;
+ } else {
+ if (p_text.nocasecmp_to(term) == 0)
+ matched_item = p_item;
+ }
+ }
+}
+
+TreeItem *EditorHelpSearch::Runner::_create_class_hierarchy(const ClassMatch &p_match) {
+
+ if (class_items.has(p_match.doc->name))
+ return class_items[p_match.doc->name];
+
+ // Ensure parent nodes are created first.
+ TreeItem *parent = root_item;
+ if (p_match.doc->inherits != "") {
+ if (class_items.has(p_match.doc->inherits)) {
+ parent = class_items[p_match.doc->inherits];
+ } else {
+ ClassMatch &base_match = matches[p_match.doc->inherits];
+ parent = _create_class_hierarchy(base_match);
+ }
+ }
+
+ TreeItem *class_item = _create_class_item(parent, p_match.doc, !p_match.name);
+ class_items[p_match.doc->name] = class_item;
+ return class_item;
+}
+
+TreeItem *EditorHelpSearch::Runner::_create_class_item(TreeItem *p_parent, const DocData::ClassDoc *p_doc, bool p_gray) {
+
+ Ref<Texture> icon = empty_icon;
+ if (ui_service->has_icon(p_doc->name, "EditorIcons"))
+ icon = ui_service->get_icon(p_doc->name, "EditorIcons");
+ else if (ClassDB::class_exists(p_doc->name) && ClassDB::is_parent_class(p_doc->name, "Object"))
+ icon = ui_service->get_icon("Object", "EditorIcons");
+ String tooltip = p_doc->brief_description.strip_edges();
+
+ TreeItem *item = results_tree->create_item(p_parent);
+ item->set_icon(0, icon);
+ item->set_text(0, p_doc->name);
+ item->set_text(1, TTR("Class"));
+ item->set_tooltip(0, tooltip);
+ item->set_tooltip(1, tooltip);
+ item->set_metadata(0, "class_name:" + p_doc->name);
+ if (p_gray) {
+ item->set_custom_color(0, disabled_color);
+ item->set_custom_color(1, disabled_color);
+ }
+
+ _match_item(item, p_doc->name);
+
+ return item;
+}
+
+TreeItem *EditorHelpSearch::Runner::_create_method_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const DocData::MethodDoc *p_doc) {
+
+ String tooltip = p_doc->return_type + " " + p_class_doc->name + "." + p_doc->name + "(";
+ for (int i = 0; i < p_doc->arguments.size(); i++) {
+ const DocData::ArgumentDoc &arg = p_doc->arguments[i];
+ tooltip += arg.type + " " + arg.name;
+ if (arg.default_value != "")
+ tooltip += " = " + arg.default_value;
+ if (i < p_doc->arguments.size() - 1)
+ tooltip += ", ";
+ }
+ tooltip += ")";
+ return _create_member_item(p_parent, p_class_doc->name, "MemberMethod", p_doc->name, "Method", "method", tooltip);
+}
+
+TreeItem *EditorHelpSearch::Runner::_create_signal_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const DocData::MethodDoc *p_doc) {
+
+ String tooltip = p_doc->return_type + " " + p_class_doc->name + "." + p_doc->name + "(";
+ for (int i = 0; i < p_doc->arguments.size(); i++) {
+ const DocData::ArgumentDoc &arg = p_doc->arguments[i];
+ tooltip += arg.type + " " + arg.name;
+ if (arg.default_value != "")
+ tooltip += " = " + arg.default_value;
+ if (i < p_doc->arguments.size() - 1)
+ tooltip += ", ";
+ }
+ tooltip += ")";
+ return _create_member_item(p_parent, p_class_doc->name, "MemberSignal", p_doc->name, "Signal", "signal", tooltip);
+}
+
+TreeItem *EditorHelpSearch::Runner::_create_constant_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const DocData::ConstantDoc *p_doc) {
+
+ String tooltip = p_class_doc->name + "." + p_doc->name;
+ return _create_member_item(p_parent, p_class_doc->name, "MemberConstant", p_doc->name, "Constant", "constant", tooltip);
+}
+
+TreeItem *EditorHelpSearch::Runner::_create_property_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const DocData::PropertyDoc *p_doc) {
+
+ String tooltip = p_doc->type + " " + p_class_doc->name + "." + p_doc->name;
+ tooltip += "\n " + p_class_doc->name + "." + p_doc->setter + "(value) setter";
+ tooltip += "\n " + p_class_doc->name + "." + p_doc->getter + "() getter";
+ return _create_member_item(p_parent, p_class_doc->name, "MemberProperty", p_doc->name, "Property", "property", tooltip);
+}
+
+TreeItem *EditorHelpSearch::Runner::_create_theme_property_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const DocData::PropertyDoc *p_doc) {
+
+ String tooltip = p_doc->type + " " + p_class_doc->name + "." + p_doc->name;
+ return _create_member_item(p_parent, p_class_doc->name, "MemberTheme", p_doc->name, "Theme Property", "theme_item", tooltip);
+}
+
+TreeItem *EditorHelpSearch::Runner::_create_member_item(TreeItem *p_parent, const String &p_class_name, const String &p_icon, const String &p_name, const String &p_type, const String &p_metatype, const String &p_tooltip) {
+
+ Ref<Texture> icon;
+ String text;
+ if (search_flags & SEARCH_SHOW_HIERARCHY) {
+ icon = ui_service->get_icon(p_icon, "EditorIcons");
+ text = p_name;
+ } else {
+ icon = ui_service->get_icon(p_icon, "EditorIcons");
+ /*// In flat mode, show the class icon.
+ if (ui_service->has_icon(p_class_name, "EditorIcons"))
+ icon = ui_service->get_icon(p_class_name, "EditorIcons");
+ else if (ClassDB::is_parent_class(p_class_name, "Object"))
+ icon = ui_service->get_icon("Object", "EditorIcons");*/
+ text = p_class_name + "." + p_name;
+ }
+
+ TreeItem *item = results_tree->create_item(p_parent);
+ item->set_icon(0, icon);
+ item->set_text(0, text);
+ item->set_text(1, TTR(p_type));
+ item->set_tooltip(0, p_tooltip);
+ item->set_tooltip(1, p_tooltip);
+ item->set_metadata(0, "class_" + p_metatype + ":" + p_class_name + ":" + p_name);
+
+ _match_item(item, p_name);
+
+ return item;
+}
+
+bool EditorHelpSearch::Runner::work(uint64_t slot) {
+
+ // Return true when the search has been completed, otherwise false.
+ const uint64_t until = OS::get_singleton()->get_ticks_usec() + slot;
+ while (!_slice())
+ if (OS::get_singleton()->get_ticks_usec() > until)
+ return false;
+ return true;
+}
+
+EditorHelpSearch::Runner::Runner(Control *p_icon_service, Tree *p_results_tree, const String &p_term, int p_search_flags) {
+
+ ui_service = p_icon_service;
+ results_tree = p_results_tree;
+ term = p_term.strip_edges();
+ search_flags = p_search_flags;
+
+ if ((search_flags & SEARCH_CASE_SENSITIVE) == 0)
+ term = term.to_lower();
+
+ empty_icon = ui_service->get_icon("ArrowRight", "EditorIcons");
+ disabled_color = ui_service->get_color("disabled_font_color", "Editor");
+
+ phase = 0;
+}
diff --git a/editor/editor_help_search.h b/editor/editor_help_search.h
new file mode 100644
index 0000000000..1016675dd2
--- /dev/null
+++ b/editor/editor_help_search.h
@@ -0,0 +1,156 @@
+/*************************************************************************/
+/* editor_help_search.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef EDITOR_HELP_SEARCH_H
+#define EDITOR_HELP_SEARCH_H
+
+#include "core/ordered_hash_map.h"
+#include "editor/code_editor.h"
+#include "editor/editor_help.h"
+#include "editor/editor_plugin.h"
+#include "scene/gui/option_button.h"
+#include "scene/gui/tree.h"
+
+class EditorHelpSearch : public ConfirmationDialog {
+ GDCLASS(EditorHelpSearch, ConfirmationDialog);
+
+ enum SearchFlags {
+ SEARCH_CLASSES = 1 << 0,
+ SEARCH_METHODS = 1 << 1,
+ SEARCH_SIGNALS = 1 << 2,
+ SEARCH_CONSTANTS = 1 << 3,
+ SEARCH_PROPERTIES = 1 << 4,
+ SEARCH_THEME_ITEMS = 1 << 5,
+ SEARCH_ALL = SEARCH_CLASSES | SEARCH_METHODS | SEARCH_SIGNALS | SEARCH_CONSTANTS | SEARCH_PROPERTIES | SEARCH_THEME_ITEMS,
+ SEARCH_CASE_SENSITIVE = 1 << 29,
+ SEARCH_SHOW_HIERARCHY = 1 << 30
+ };
+
+ LineEdit *search_box;
+ ToolButton *case_sensitive_button;
+ ToolButton *hierarchy_button;
+ OptionButton *filter_combo;
+ Tree *results_tree;
+
+ class Runner;
+ Ref<Runner> search;
+
+ void _update_icons();
+ void _load_settings();
+ void _update_results();
+
+ void _search_box_gui_input(const Ref<InputEvent> &p_ie);
+ void _search_box_text_changed(const String &p_text);
+ void _case_sensitive_button_pressed();
+ void _hierarchy_button_pressed();
+ void _filter_combo_item_selected(int p_option);
+ void _confirmed();
+
+protected:
+ void _notification(int p_what);
+ static void _bind_methods();
+
+public:
+ void popup_dialog();
+ void popup_dialog(const String &p_term);
+
+ EditorHelpSearch();
+};
+
+class EditorHelpSearch::Runner : public Reference {
+
+ enum Phase {
+ PHASE_MATCH_CLASSES_INIT,
+ PHASE_MATCH_CLASSES,
+ PHASE_CLASS_ITEMS_INIT,
+ PHASE_CLASS_ITEMS,
+ PHASE_MEMBER_ITEMS_INIT,
+ PHASE_MEMBER_ITEMS,
+ PHASE_SELECT_MATCH,
+ PHASE_MAX
+ };
+ int phase;
+
+ struct ClassMatch {
+ DocData::ClassDoc *doc;
+ bool name;
+ Vector<DocData::MethodDoc *> methods;
+ Vector<DocData::MethodDoc *> signals;
+ Vector<DocData::ConstantDoc *> constants;
+ Vector<DocData::PropertyDoc *> properties;
+ Vector<DocData::PropertyDoc *> theme_properties;
+
+ bool required() {
+ return name || methods.size() || signals.size() || constants.size() || properties.size() || theme_properties.size();
+ }
+ };
+
+ Control *ui_service;
+ Tree *results_tree;
+ String term;
+ int search_flags;
+
+ Ref<Texture> empty_icon;
+ Color disabled_color;
+
+ Map<String, DocData::ClassDoc>::Element *iterator_doc;
+ Map<String, ClassMatch> matches;
+ Map<String, ClassMatch>::Element *iterator_match;
+ TreeItem *root_item;
+ Map<String, TreeItem *> class_items;
+ TreeItem *matched_item;
+
+ bool _slice();
+ bool _phase_match_classes_init();
+ bool _phase_match_classes();
+ bool _phase_class_items_init();
+ bool _phase_class_items();
+ bool _phase_member_items_init();
+ bool _phase_member_items();
+ bool _phase_select_match();
+
+ bool _match_string(const String &p_term, const String &p_string) const;
+ void _match_item(TreeItem *p_item, const String &p_text);
+ TreeItem *_create_class_hierarchy(const ClassMatch &p_match);
+ TreeItem *_create_class_item(TreeItem *p_parent, const DocData::ClassDoc *p_doc, bool p_gray);
+ TreeItem *_create_method_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const DocData::MethodDoc *p_doc);
+ TreeItem *_create_signal_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const DocData::MethodDoc *p_doc);
+ TreeItem *_create_constant_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const DocData::ConstantDoc *p_doc);
+ TreeItem *_create_property_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const DocData::PropertyDoc *p_doc);
+ TreeItem *_create_theme_property_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const DocData::PropertyDoc *p_doc);
+ TreeItem *_create_member_item(TreeItem *p_parent, const String &p_class_name, const String &p_icon, const String &p_name, const String &p_type, const String &p_metatype, const String &p_tooltip);
+
+public:
+ bool work(uint64_t slot = 100000);
+
+ Runner(Control *p_icon_service, Tree *p_results_tree, const String &p_term, int p_search_flags);
+};
+
+#endif // EDITOR_HELP_SEARCH_H
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index dbbf5d08b8..3129ef3508 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -384,7 +384,6 @@ void EditorNode::_notification(int p_what) {
update_menu->set_icon(gui_base->get_icon("Progress1", "EditorIcons"));
PopupMenu *p = help_menu->get_popup();
- p->set_item_icon(p->get_item_index(HELP_CLASSES), gui_base->get_icon("ClassList", "EditorIcons"));
p->set_item_icon(p->get_item_index(HELP_SEARCH), gui_base->get_icon("HelpSearch", "EditorIcons"));
p->set_item_icon(p->get_item_index(HELP_DOCS), gui_base->get_icon("Instance", "EditorIcons"));
p->set_item_icon(p->get_item_index(HELP_QA), gui_base->get_icon("Instance", "EditorIcons"));
@@ -410,51 +409,50 @@ void EditorNode::_on_plugin_ready(Object *p_script, const String &p_activate_nam
push_item(script.operator->());
}
-void EditorNode::_fs_changed() {
+void EditorNode::_resources_changed(const PoolVector<String> &p_resources) {
- for (Set<FileDialog *>::Element *E = file_dialogs.front(); E; E = E->next()) {
+ List<Ref<Resource> > changed;
- E->get()->invalidate();
- }
+ int rc = p_resources.size();
+ for (int i = 0; i < rc; i++) {
- for (Set<EditorFileDialog *>::Element *E = editor_file_dialogs.front(); E; E = E->next()) {
+ Ref<Resource> res(ResourceCache::get(p_resources.get(i)));
+ if (res.is_null()) {
+ continue;
+ }
- E->get()->invalidate();
- }
+ if (!res->editor_can_reload_from_file())
+ continue;
+ if (!res->get_path().is_resource_file() && !res->get_path().is_abs_path())
+ continue;
+ if (!FileAccess::exists(res->get_path()))
+ continue;
- {
- //reload changed resources
- List<Ref<Resource> > changed;
+ if (res->get_import_path() != String()) {
+ //this is an imported resource, will be reloaded if reimported via the _resources_reimported() callback
+ continue;
+ }
- List<Ref<Resource> > cached;
- ResourceCache::get_cached_resources(&cached);
- // FIXME: This should be done in a thread.
- for (List<Ref<Resource> >::Element *E = cached.front(); E; E = E->next()) {
+ changed.push_back(res);
+ }
- if (!E->get()->editor_can_reload_from_file())
- continue;
- if (!E->get()->get_path().is_resource_file() && !E->get()->get_path().is_abs_path())
- continue;
- if (!FileAccess::exists(E->get()->get_path()))
- continue;
+ if (changed.size()) {
+ for (List<Ref<Resource> >::Element *E = changed.front(); E; E = E->next()) {
+ E->get()->reload_from_file();
+ }
+ }
+}
- if (E->get()->get_import_path() != String()) {
- //this is an imported resource, will be reloaded if reimported via the _resources_reimported() callback
- continue;
- }
+void EditorNode::_fs_changed() {
- uint64_t mt = FileAccess::get_modified_time(E->get()->get_path());
+ for (Set<FileDialog *>::Element *E = file_dialogs.front(); E; E = E->next()) {
- if (mt != E->get()->get_last_modified_time()) {
- changed.push_back(E->get());
- }
- }
+ E->get()->invalidate();
+ }
- if (changed.size()) {
- for (List<Ref<Resource> >::Element *E = changed.front(); E; E = E->next()) {
- E->get()->reload_from_file();
- }
- }
+ for (Set<EditorFileDialog *>::Element *E = editor_file_dialogs.front(); E; E = E->next()) {
+
+ E->get()->invalidate();
}
_mark_unsaved_scenes();
@@ -637,6 +635,7 @@ void EditorNode::save_resource(const Ref<Resource> &p_resource) {
void EditorNode::save_resource_as(const Ref<Resource> &p_resource, const String &p_at_path) {
file->set_mode(EditorFileDialog::MODE_SAVE_FILE);
+ saving_resource = p_resource;
current_option = RESOURCE_SAVE_AS;
List<String> extensions;
@@ -1263,15 +1262,13 @@ void EditorNode::_dialog_action(String p_file) {
case RESOURCE_SAVE:
case RESOURCE_SAVE_AS: {
- uint32_t current = editor_history.get_current();
+ ERR_FAIL_COND(saving_resource.is_null())
+ save_resource_in_path(saving_resource, p_file);
+ saving_resource = Ref<Resource>();
+ ObjectID current = editor_history.get_current();
Object *current_obj = current > 0 ? ObjectDB::get_instance(current) : NULL;
-
- ERR_FAIL_COND(!Object::cast_to<Resource>(current_obj))
-
- RES current_res = RES(Object::cast_to<Resource>(current_obj));
-
- save_resource_in_path(current_res, p_file);
-
+ ERR_FAIL_COND(!current_obj);
+ current_obj->_change_notify();
} break;
case SETTINGS_LAYOUT_SAVE: {
@@ -2003,7 +2000,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
if (err != OK)
ERR_PRINT("Failed to load scene");
editor_data.move_edited_scene_to_index(cur_idx);
- get_undo_redo()->clear_history();
+ get_undo_redo()->clear_history(false);
scene_tabs->set_current_tab(cur_idx);
} break;
@@ -2263,9 +2260,6 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
file->popup_centered_ratio();
} break;
- case HELP_CLASSES: {
- emit_signal("request_help_index", "");
- } break;
case HELP_SEARCH: {
emit_signal("request_help_search", "");
} break;
@@ -2570,6 +2564,12 @@ void EditorNode::set_addon_plugin_enabled(const String &p_addon, bool p_enabled)
return;
}
+ //errors in the script cause the base_type to be ""
+ if (String(script->get_instance_base_type()) == "") {
+ show_warning(vformat(TTR("Unable to load addon script from path: '%s' There seems to be an error in the code, please check the syntax."), path));
+ return;
+ }
+
//could check inheritance..
if (String(script->get_instance_base_type()) != "EditorPlugin") {
show_warning(vformat(TTR("Unable to load addon script from path: '%s' Base type is not EditorPlugin."), path));
@@ -2613,7 +2613,7 @@ void EditorNode::_remove_edited_scene() {
}
_scene_tab_changed(new_index);
editor_data.remove_scene(old_index);
- editor_data.get_undo_redo().clear_history();
+ editor_data.get_undo_redo().clear_history(false);
_update_title();
_update_scene_tabs();
}
@@ -4651,11 +4651,12 @@ void EditorNode::_bind_methods() {
ClassDB::bind_method(D_METHOD("_video_driver_selected"), &EditorNode::_video_driver_selected);
+ ClassDB::bind_method(D_METHOD("_resources_changed"), &EditorNode::_resources_changed);
+
ADD_SIGNAL(MethodInfo("play_pressed"));
ADD_SIGNAL(MethodInfo("pause_pressed"));
ADD_SIGNAL(MethodInfo("stop_pressed"));
ADD_SIGNAL(MethodInfo("request_help_search"));
- ADD_SIGNAL(MethodInfo("request_help_index"));
ADD_SIGNAL(MethodInfo("script_add_function_request", PropertyInfo(Variant::OBJECT, "obj"), PropertyInfo(Variant::STRING, "function"), PropertyInfo(Variant::POOL_STRING_ARRAY, "args")));
ADD_SIGNAL(MethodInfo("resource_saved", PropertyInfo(Variant::OBJECT, "obj")));
}
@@ -5341,8 +5342,7 @@ EditorNode::EditorNode() {
p = help_menu->get_popup();
p->set_hide_on_window_lose_focus(true);
p->connect("id_pressed", this, "_menu_option");
- p->add_icon_item(gui_base->get_icon("ClassList", "EditorIcons"), TTR("Classes"), HELP_CLASSES);
- p->add_icon_item(gui_base->get_icon("HelpSearch", "EditorIcons"), TTR("Search"), HELP_SEARCH);
+ p->add_icon_shortcut(gui_base->get_icon("HelpSearch", "EditorIcons"), ED_SHORTCUT("editor/editor_help", TTR("Search"), KEY_F4), HELP_SEARCH);
p->add_separator();
p->add_icon_item(gui_base->get_icon("Instance", "EditorIcons"), TTR("Online Docs"), HELP_DOCS);
p->add_icon_item(gui_base->get_icon("Instance", "EditorIcons"), TTR("Q&A"), HELP_QA);
@@ -5777,6 +5777,7 @@ EditorNode::EditorNode() {
_edit_current();
current = NULL;
+ saving_resource = Ref<Resource>();
reference_resource_mem = true;
save_external_resources_mem = true;
@@ -5819,6 +5820,7 @@ EditorNode::EditorNode() {
EditorFileSystem::get_singleton()->connect("sources_changed", this, "_sources_changed");
EditorFileSystem::get_singleton()->connect("filesystem_changed", this, "_fs_changed");
EditorFileSystem::get_singleton()->connect("resources_reimported", this, "_resources_reimported");
+ EditorFileSystem::get_singleton()->connect("resources_reload", this, "_resources_changed");
_build_icon_type_cache();
diff --git a/editor/editor_node.h b/editor/editor_node.h
index b828a4d7d5..e220daf8a9 100644
--- a/editor/editor_node.h
+++ b/editor/editor_node.h
@@ -180,7 +180,6 @@ private:
SETTINGS_HELP,
SCENE_TAB_CLOSE,
- HELP_CLASSES,
HELP_SEARCH,
HELP_DOCS,
HELP_QA,
@@ -356,6 +355,7 @@ private:
EditorExport *editor_export;
Object *current;
+ Ref<Resource> saving_resource;
bool _playing_edited;
String run_custom_filename;
@@ -605,6 +605,8 @@ private:
static void _resource_saved(RES p_resource, const String &p_path);
static void _resource_loaded(RES p_resource, const String &p_path);
+ void _resources_changed(const PoolVector<String> &p_resources);
+
protected:
void _notification(int p_what);
static void _bind_methods();
diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp
index 3730807243..57c6fa3547 100644
--- a/editor/editor_properties.cpp
+++ b/editor/editor_properties.cpp
@@ -1802,14 +1802,26 @@ void EditorPropertyNodePath::_node_selected(const NodePath &p_path) {
NodePath path = p_path;
Node *base_node = Object::cast_to<Node>(get_edited_object());
- if (base_node == NULL) {
- if (Object::cast_to<Resource>(get_edited_object())) {
- Node *to_node = get_node(p_path);
- path = get_tree()->get_edited_scene_root()->get_path_to(to_node);
- } else if (get_edited_object()->has_method("get_root_path")) {
- base_node = get_edited_object()->call("get_root_path");
+ if (!base_node) {
+ //try a base node within history
+ if (EditorNode::get_singleton()->get_editor_history()->get_path_size() > 0) {
+ Object *base = ObjectDB::get_instance(EditorNode::get_singleton()->get_editor_history()->get_path_object(0));
+ if (base) {
+ base_node = Object::cast_to<Node>(base);
+ }
}
}
+
+ if (!base_node && get_edited_object()->has_method("get_root_path")) {
+ base_node = get_edited_object()->call("get_root_path");
+ }
+
+ if (!base_node && Object::cast_to<Reference>(get_edited_object())) {
+ Node *to_node = get_node(p_path);
+ ERR_FAIL_COND(!to_node);
+ path = get_tree()->get_edited_scene_root()->get_path_to(to_node);
+ }
+
if (base_node) { // for AnimationTrackKeyEdit
path = base_node->get_path().rel_path_to(p_path);
}
@@ -2016,6 +2028,13 @@ void EditorPropertyResource::_menu_option(int p_which) {
} break;
+ case OBJ_MENU_SAVE: {
+ RES res = get_edited_object()->get(get_edited_property());
+ if (res.is_null())
+ return;
+ EditorNode::get_singleton()->save_resource(res);
+ } break;
+
case OBJ_MENU_COPY: {
RES res = get_edited_object()->get(get_edited_property());
@@ -2233,6 +2252,7 @@ void EditorPropertyResource::_update_menu_items() {
menu->add_icon_item(get_icon("Edit", "EditorIcons"), TTR("Edit"), OBJ_MENU_EDIT);
menu->add_icon_item(get_icon("Clear", "EditorIcons"), TTR("Clear"), OBJ_MENU_CLEAR);
menu->add_icon_item(get_icon("Duplicate", "EditorIcons"), TTR("Make Unique"), OBJ_MENU_MAKE_UNIQUE);
+ menu->add_icon_item(get_icon("Save", "EditorIcons"), TTR("Save"), OBJ_MENU_SAVE);
RES r = res;
if (r.is_valid() && r->get_path().is_resource_file()) {
menu->add_separator();
diff --git a/editor/editor_properties.h b/editor/editor_properties.h
index 541abb1f22..b82ef977ef 100644
--- a/editor/editor_properties.h
+++ b/editor/editor_properties.h
@@ -522,10 +522,11 @@ class EditorPropertyResource : public EditorProperty {
OBJ_MENU_EDIT = 1,
OBJ_MENU_CLEAR = 2,
OBJ_MENU_MAKE_UNIQUE = 3,
- OBJ_MENU_COPY = 4,
- OBJ_MENU_PASTE = 5,
- OBJ_MENU_NEW_SCRIPT = 6,
- OBJ_MENU_SHOW_IN_FILE_SYSTEM = 7,
+ OBJ_MENU_SAVE = 4,
+ OBJ_MENU_COPY = 5,
+ OBJ_MENU_PASTE = 6,
+ OBJ_MENU_NEW_SCRIPT = 7,
+ OBJ_MENU_SHOW_IN_FILE_SYSTEM = 8,
TYPE_BASE_ID = 100,
CONVERT_BASE_ID = 1000
diff --git a/editor/editor_properties_array_dict.cpp b/editor/editor_properties_array_dict.cpp
index 24360813a2..431f608f46 100644
--- a/editor/editor_properties_array_dict.cpp
+++ b/editor/editor_properties_array_dict.cpp
@@ -29,9 +29,9 @@
/*************************************************************************/
#include "editor_properties_array_dict.h"
+#include "core/io/marshalls.h"
#include "editor/editor_scale.h"
#include "editor_properties.h"
-
bool EditorPropertyArrayObject::_set(const StringName &p_name, const Variant &p_value) {
String pn = p_name;
@@ -54,6 +54,10 @@ bool EditorPropertyArrayObject::_get(const StringName &p_name, Variant &r_ret) c
int idx = pn.get_slicec('/', 1).to_int();
bool valid;
r_ret = array.get(idx, &valid);
+ if (r_ret.get_type() == Variant::OBJECT && Object::cast_to<EncodedObjectAsID>(r_ret)) {
+ r_ret = Object::cast_to<EncodedObjectAsID>(r_ret)->get_object_id();
+ }
+
return valid;
}
@@ -120,6 +124,10 @@ bool EditorPropertyDictionaryObject::_get(const StringName &p_name, Variant &r_r
int idx = pn.get_slicec('/', 1).to_int();
Variant key = dict.get_key_at_index(idx);
r_ret = dict[key];
+ if (r_ret.get_type() == Variant::OBJECT && Object::cast_to<EncodedObjectAsID>(r_ret)) {
+ r_ret = Object::cast_to<EncodedObjectAsID>(r_ret)->get_object_id();
+ }
+
return true;
}
@@ -198,6 +206,10 @@ void EditorPropertyArray::_change_type_menu(int p_index) {
update_property();
}
+void EditorPropertyArray::_object_id_selected(const String &p_property, ObjectID p_id) {
+ emit_signal("object_id_selected", p_property, p_id);
+}
+
void EditorPropertyArray::update_property() {
Variant array = get_edited_object()->get(get_edited_property());
@@ -431,9 +443,19 @@ void EditorPropertyArray::update_property() {
} break;
case Variant::OBJECT: {
- EditorPropertyResource *editor = memnew(EditorPropertyResource);
- editor->setup("Resource");
- prop = editor;
+
+ if (Object::cast_to<EncodedObjectAsID>(value)) {
+
+ EditorPropertyObjectID *editor = memnew(EditorPropertyObjectID);
+ editor->setup("Object");
+ prop = editor;
+
+ } else {
+
+ EditorPropertyResource *editor = memnew(EditorPropertyResource);
+ editor->setup("Resource");
+ prop = editor;
+ }
} break;
case Variant::DICTIONARY: {
@@ -497,6 +519,7 @@ void EditorPropertyArray::update_property() {
prop->set_label(itos(i + offset));
prop->set_selectable(false);
prop->connect("property_changed", this, "_property_changed");
+ prop->connect("object_id_selected", this, "_object_id_selected");
if (array.get_type() == Variant::ARRAY) {
HBoxContainer *hb = memnew(HBoxContainer);
vbox->add_child(hb);
@@ -578,6 +601,7 @@ void EditorPropertyArray::_bind_methods() {
ClassDB::bind_method("_property_changed", &EditorPropertyArray::_property_changed, DEFVAL(false));
ClassDB::bind_method("_change_type", &EditorPropertyArray::_change_type);
ClassDB::bind_method("_change_type_menu", &EditorPropertyArray::_change_type_menu);
+ ClassDB::bind_method("_object_id_selected", &EditorPropertyArray::_object_id_selected);
}
EditorPropertyArray::EditorPropertyArray() {
@@ -893,9 +917,19 @@ void EditorPropertyDictionary::update_property() {
} break;
case Variant::OBJECT: {
- EditorPropertyResource *editor = memnew(EditorPropertyResource);
- editor->setup("Resource");
- prop = editor;
+
+ if (Object::cast_to<EncodedObjectAsID>(value)) {
+
+ EditorPropertyObjectID *editor = memnew(EditorPropertyObjectID);
+ editor->setup("Object");
+ prop = editor;
+
+ } else {
+
+ EditorPropertyResource *editor = memnew(EditorPropertyResource);
+ editor->setup("Resource");
+ prop = editor;
+ }
} break;
case Variant::DICTIONARY: {
@@ -986,6 +1020,7 @@ void EditorPropertyDictionary::update_property() {
prop->set_selectable(false);
prop->connect("property_changed", this, "_property_changed");
+ prop->connect("object_id_selected", this, "_object_id_selected");
HBoxContainer *hb = memnew(HBoxContainer);
if (add_vbox) {
@@ -1022,6 +1057,10 @@ void EditorPropertyDictionary::update_property() {
#endif
}
+void EditorPropertyDictionary::_object_id_selected(const String &p_property, ObjectID p_id) {
+ emit_signal("object_id_selected", p_property, p_id);
+}
+
void EditorPropertyDictionary::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) {
@@ -1055,6 +1094,7 @@ void EditorPropertyDictionary::_bind_methods() {
ClassDB::bind_method("_change_type", &EditorPropertyDictionary::_change_type);
ClassDB::bind_method("_change_type_menu", &EditorPropertyDictionary::_change_type_menu);
ClassDB::bind_method("_add_key_value", &EditorPropertyDictionary::_add_key_value);
+ ClassDB::bind_method("_object_id_selected", &EditorPropertyDictionary::_object_id_selected);
}
EditorPropertyDictionary::EditorPropertyDictionary() {
diff --git a/editor/editor_properties_array_dict.h b/editor/editor_properties_array_dict.h
index d2bd849f30..d5eecd9106 100644
--- a/editor/editor_properties_array_dict.h
+++ b/editor/editor_properties_array_dict.h
@@ -101,6 +101,8 @@ class EditorPropertyArray : public EditorProperty {
void _change_type(Object *p_button, int p_index);
void _change_type_menu(int p_index);
+ void _object_id_selected(const String &p_property, ObjectID p_id);
+
protected:
static void _bind_methods();
void _notification(int p_what);
@@ -134,6 +136,7 @@ class EditorPropertyDictionary : public EditorProperty {
void _change_type_menu(int p_index);
void _add_key_value();
+ void _object_id_selected(const String &p_property, ObjectID p_id);
protected:
static void _bind_methods();
diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp
index c0b441bbd5..fdfa094ba2 100644
--- a/editor/editor_settings.cpp
+++ b/editor/editor_settings.cpp
@@ -300,6 +300,8 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
hints["interface/editor/main_font_size"] = PropertyInfo(Variant::INT, "interface/editor/main_font_size", PROPERTY_HINT_RANGE, "10,40,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED);
_initial_set("interface/editor/code_font_size", 14);
hints["interface/editor/code_font_size"] = PropertyInfo(Variant::INT, "interface/editor/code_font_size", PROPERTY_HINT_RANGE, "8,96,1", PROPERTY_USAGE_DEFAULT);
+ _initial_set("interface/editor/main_font_antialiased", true);
+ _initial_set("interface/editor/code_font_antialiased", true);
_initial_set("interface/editor/main_font_hinting", 2);
hints["interface/editor/main_font_hinting"] = PropertyInfo(Variant::INT, "interface/editor/main_font_hinting", PROPERTY_HINT_ENUM, "None,Light,Normal", PROPERTY_USAGE_DEFAULT);
_initial_set("interface/editor/code_font_hinting", 2);
diff --git a/editor/import/editor_import_collada.cpp b/editor/import/editor_import_collada.cpp
index 65ccfc9309..afd09748f3 100644
--- a/editor/import/editor_import_collada.cpp
+++ b/editor/import/editor_import_collada.cpp
@@ -771,7 +771,7 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<ArrayMesh> &p_me
int binormal_pos = (binormal_src->stride ? binormal_src->stride : 3) * p.indices[src + binormal_ofs];
ERR_FAIL_INDEX_V(binormal_pos, binormal_src->array.size(), ERR_INVALID_DATA);
- Vector3 binormal = Vector3(binormal_src->array[binormal_pos + 0], binormal_src->array[binormal_pos + 1], binormal_src->array[binormal_pos + 2]);
+ Vector3 binormal = Vector3(-binormal_src->array[binormal_pos + 0], -binormal_src->array[binormal_pos + 1], -binormal_src->array[binormal_pos + 2]); // Due to Godots face order it seems we need to flip our binormal!
int tangent_pos = (tangent_src->stride ? tangent_src->stride : 3) * p.indices[src + tangent_ofs];
ERR_FAIL_INDEX_V(tangent_pos, tangent_src->array.size(), ERR_INVALID_DATA);
diff --git a/editor/import/editor_scene_importer_gltf.cpp b/editor/import/editor_scene_importer_gltf.cpp
index cb15be35f2..00ca86a43b 100644
--- a/editor/import/editor_scene_importer_gltf.cpp
+++ b/editor/import/editor_scene_importer_gltf.cpp
@@ -899,7 +899,16 @@ Error EditorSceneImporterGLTF::_parse_meshes(GLTFState &state) {
array[Mesh::ARRAY_NORMAL] = _decode_accessor_as_vec3(state, a["NORMAL"], true);
}
if (a.has("TANGENT")) {
- array[Mesh::ARRAY_TANGENT] = _decode_accessor_as_floats(state, a["TANGENT"], true);
+ PoolVector<float> tans = _decode_accessor_as_floats(state, a["TANGENT"], true);
+ { // we need our binormals inversed, so flip our w component.
+ int ts = tans.size();
+ PoolVector<float>::Write w = tans.write();
+
+ for (int j = 3; j < ts; j += 4) {
+ w[j] *= -1.0;
+ }
+ }
+ array[Mesh::ARRAY_TANGENT] = tans;
}
if (a.has("TEXCOORD_0")) {
array[Mesh::ARRAY_TEX_UV] = _decode_accessor_as_vec2(state, a["TEXCOORD_0"], true);
@@ -1686,7 +1695,7 @@ void EditorSceneImporterGLTF::_generate_node(GLTFState &state, int p_node, Node
n->godot_nodes.push_back(node);
- if (n->skin >= 0 && Object::cast_to<MeshInstance>(node)) {
+ if (n->skin >= 0 && n->skin < skeletons.size() && Object::cast_to<MeshInstance>(node)) {
MeshInstance *mi = Object::cast_to<MeshInstance>(node);
Skeleton *s = skeletons[n->skin];
diff --git a/editor/import/resource_importer_texture.cpp b/editor/import/resource_importer_texture.cpp
index 8e91a88adb..b38f4c4f14 100644
--- a/editor/import/resource_importer_texture.cpp
+++ b/editor/import/resource_importer_texture.cpp
@@ -216,7 +216,7 @@ void ResourceImporterTexture::get_import_options(List<ImportOption> *r_options,
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "stream"), false));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "size_limit", PROPERTY_HINT_RANGE, "0,4096,1"), 0));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "detect_3d"), p_preset == PRESET_DETECT));
- r_options->push_back(ImportOption(PropertyInfo(Variant::REAL, "svg/scale", PROPERTY_HINT_RANGE, "0.001,100,0.1"), 1.0));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::REAL, "svg/scale", PROPERTY_HINT_RANGE, "0.001,100,0.001"), 1.0));
}
void ResourceImporterTexture::_save_stex(const Ref<Image> &p_image, const String &p_to_path, int p_compress_mode, float p_lossy_quality, Image::CompressMode p_vram_compression, bool p_mipmaps, int p_texture_flags, bool p_streamable, bool p_detect_3d, bool p_detect_srgb, bool p_force_rgbe, bool p_detect_normal, bool p_force_normal) {
diff --git a/editor/plugins/animation_blend_space_2d_editor.cpp b/editor/plugins/animation_blend_space_2d_editor.cpp
index 394b888d0e..e2fe9a91d8 100644
--- a/editor/plugins/animation_blend_space_2d_editor.cpp
+++ b/editor/plugins/animation_blend_space_2d_editor.cpp
@@ -607,6 +607,8 @@ void AnimationNodeBlendSpace2DEditor::_update_space() {
auto_triangles->set_pressed(blend_space->get_auto_triangles());
+ interpolation->select(blend_space->get_blend_mode());
+
max_x_value->set_value(blend_space->get_max_space().x);
max_y_value->set_value(blend_space->get_max_space().y);
@@ -636,6 +638,8 @@ void AnimationNodeBlendSpace2DEditor::_config_changed(double) {
undo_redo->add_undo_method(blend_space.ptr(), "set_min_space", blend_space->get_min_space());
undo_redo->add_do_method(blend_space.ptr(), "set_snap", Vector2(snap_x->get_value(), snap_y->get_value()));
undo_redo->add_undo_method(blend_space.ptr(), "set_snap", blend_space->get_snap());
+ undo_redo->add_do_method(blend_space.ptr(), "set_blend_mode", interpolation->get_selected());
+ undo_redo->add_undo_method(blend_space.ptr(), "set_blend_mode", blend_space->get_blend_mode());
undo_redo->add_do_method(this, "_update_space");
undo_redo->add_undo_method(this, "_update_space");
undo_redo->commit_action();
@@ -752,6 +756,10 @@ void AnimationNodeBlendSpace2DEditor::_notification(int p_what) {
snap->set_icon(get_icon("SnapGrid", "EditorIcons"));
open_editor->set_icon(get_icon("Edit", "EditorIcons"));
auto_triangles->set_icon(get_icon("AutoTriangle", "EditorIcons"));
+ interpolation->clear();
+ interpolation->add_icon_item(get_icon("TrackContinuous", "EditorIcons"), "", 0);
+ interpolation->add_icon_item(get_icon("TrackDiscrete", "EditorIcons"), "", 1);
+ interpolation->add_icon_item(get_icon("TrackCapture", "EditorIcons"), "", 2);
}
if (p_what == NOTIFICATION_PROCESS) {
@@ -914,6 +922,13 @@ AnimationNodeBlendSpace2DEditor::AnimationNodeBlendSpace2DEditor() {
snap_y->set_step(0.01);
snap_y->set_max(1000);
+ top_hb->add_child(memnew(VSeparator));
+
+ top_hb->add_child(memnew(Label(TTR("Blend:"))));
+ interpolation = memnew(OptionButton);
+ top_hb->add_child(interpolation);
+ interpolation->connect("item_selected", this, "_config_changed");
+
edit_hb = memnew(HBoxContainer);
top_hb->add_child(edit_hb);
edit_hb->add_child(memnew(VSeparator));
diff --git a/editor/plugins/animation_blend_space_2d_editor.h b/editor/plugins/animation_blend_space_2d_editor.h
index 613289e4d8..603fa1cd19 100644
--- a/editor/plugins/animation_blend_space_2d_editor.h
+++ b/editor/plugins/animation_blend_space_2d_editor.h
@@ -60,6 +60,7 @@ class AnimationNodeBlendSpace2DEditor : public AnimationTreeNodeEditorPlugin {
ToolButton *snap;
SpinBox *snap_x;
SpinBox *snap_y;
+ OptionButton *interpolation;
ToolButton *auto_triangles;
diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp
index 085660b79e..ae6fa8e6bb 100644
--- a/editor/plugins/script_editor_plugin.cpp
+++ b/editor/plugins/script_editor_plugin.cpp
@@ -50,8 +50,7 @@ void ScriptEditorBase::_bind_methods() {
ADD_SIGNAL(MethodInfo("name_changed"));
ADD_SIGNAL(MethodInfo("edited_script_changed"));
- ADD_SIGNAL(MethodInfo("request_help_search", PropertyInfo(Variant::STRING, "topic")));
- ADD_SIGNAL(MethodInfo("request_help_index"));
+ ADD_SIGNAL(MethodInfo("request_help", PropertyInfo(Variant::STRING, "topic")));
ADD_SIGNAL(MethodInfo("request_open_script_at_line", PropertyInfo(Variant::OBJECT, "script"), PropertyInfo(Variant::INT, "line")));
ADD_SIGNAL(MethodInfo("request_save_history"));
ADD_SIGNAL(MethodInfo("go_to_help", PropertyInfo(Variant::STRING, "what")));
@@ -975,10 +974,6 @@ void ScriptEditor::_menu_option(int p_option) {
help_search_dialog->popup_dialog();
} break;
- case SEARCH_CLASSES: {
-
- help_index->popup_dialog();
- } break;
case SEARCH_WEBSITE: {
OS::get_singleton()->shell_open("https://docs.godotengine.org/");
@@ -1206,12 +1201,6 @@ void ScriptEditor::_menu_option(int p_option) {
if (help) {
switch (p_option) {
-
- case SEARCH_CLASSES: {
-
- help_index->popup_dialog();
- help_index->call_deferred("select_class", help->get_class());
- } break;
case HELP_SEARCH_FIND: {
help->popup_search();
} break;
@@ -1318,7 +1307,6 @@ void ScriptEditor::_notification(int p_what) {
EditorSettings::get_singleton()->connect("settings_changed", this, "_editor_settings_changed");
help_search->set_icon(get_icon("HelpSearch", "EditorIcons"));
site_search->set_icon(get_icon("Instance", "EditorIcons"));
- class_search->set_icon(get_icon("ClassList", "EditorIcons"));
script_forward->set_icon(get_icon("Forward", "EditorIcons"));
script_back->set_icon(get_icon("Back", "EditorIcons"));
@@ -1330,7 +1318,6 @@ void ScriptEditor::_notification(int p_what) {
get_tree()->connect("tree_changed", this, "_tree_changed");
editor->get_inspector_dock()->connect("request_help", this, "_request_help");
editor->connect("request_help_search", this, "_help_search");
- editor->connect("request_help_index", this, "_help_index");
} break;
case NOTIFICATION_EXIT_TREE: {
@@ -1350,7 +1337,6 @@ void ScriptEditor::_notification(int p_what) {
help_search->set_icon(get_icon("HelpSearch", "EditorIcons"));
site_search->set_icon(get_icon("Instance", "EditorIcons"));
- class_search->set_icon(get_icon("ClassList", "EditorIcons"));
script_forward->set_icon(get_icon("Forward", "EditorIcons"));
script_back->set_icon(get_icon("Back", "EditorIcons"));
@@ -2006,7 +1992,7 @@ bool ScriptEditor::edit(const RES &p_resource, int p_line, int p_col, bool p_gra
_save_layout();
se->connect("name_changed", this, "_update_script_names");
se->connect("edited_script_changed", this, "_script_changed");
- se->connect("request_help_search", this, "_help_search");
+ se->connect("request_help", this, "_help_search");
se->connect("request_open_script_at_line", this, "_goto_script_line");
se->connect("go_to_help", this, "_help_class_goto");
se->connect("request_save_history", this, "_save_history");
@@ -2733,10 +2719,6 @@ void ScriptEditor::set_live_auto_reload_running_scripts(bool p_enabled) {
auto_reload_running_scripts = p_enabled;
}
-void ScriptEditor::_help_index(String p_text) {
- help_index->popup_dialog();
-}
-
void ScriptEditor::_help_search(String p_text) {
help_search_dialog->popup_dialog(p_text);
}
@@ -2842,7 +2824,6 @@ void ScriptEditor::_bind_methods() {
ClassDB::bind_method("_goto_script_line", &ScriptEditor::_goto_script_line);
ClassDB::bind_method("_goto_script_line2", &ScriptEditor::_goto_script_line2);
ClassDB::bind_method("_help_search", &ScriptEditor::_help_search);
- ClassDB::bind_method("_help_index", &ScriptEditor::_help_index);
ClassDB::bind_method("_save_history", &ScriptEditor::_save_history);
ClassDB::bind_method("_copy_script_path", &ScriptEditor::_copy_script_path);
@@ -3077,12 +3058,6 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) {
menu_hb->add_child(site_search);
site_search->set_tooltip(TTR("Open Godot online documentation"));
- class_search = memnew(ToolButton);
- class_search->set_text(TTR("Classes"));
- class_search->connect("pressed", this, "_menu_option", varray(SEARCH_CLASSES));
- menu_hb->add_child(class_search);
- class_search->set_tooltip(TTR("Search the class hierarchy."));
-
help_search = memnew(ToolButton);
help_search->set_text(TTR("Search Help"));
help_search->connect("pressed", this, "_menu_option", varray(SEARCH_HELP));
@@ -3168,10 +3143,6 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) {
add_child(help_search_dialog);
help_search_dialog->connect("go_to_help", this, "_help_class_goto");
- help_index = memnew(EditorHelpIndex);
- add_child(help_index);
- help_index->connect("open_class", this, "_help_class_open");
-
find_in_files_dialog = memnew(FindInFilesDialog);
find_in_files_dialog->connect(FindInFilesDialog::SIGNAL_FIND_REQUESTED, this, "_start_find_in_files", varray(false));
find_in_files_dialog->connect(FindInFilesDialog::SIGNAL_REPLACE_REQUESTED, this, "_start_find_in_files", varray(true));
diff --git a/editor/plugins/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h
index 28c07393f7..4be5345aaa 100644
--- a/editor/plugins/script_editor_plugin.h
+++ b/editor/plugins/script_editor_plugin.h
@@ -34,6 +34,7 @@
#include "core/script_language.h"
#include "editor/code_editor.h"
#include "editor/editor_help.h"
+#include "editor/editor_help_search.h"
#include "editor/editor_plugin.h"
#include "editor/script_create_dialog.h"
#include "scene/gui/item_list.h"
@@ -155,7 +156,6 @@ class ScriptEditor : public PanelContainer {
DEBUG_SHOW_KEEP_OPEN,
DEBUG_WITH_EXTERNAL_EDITOR,
SEARCH_HELP,
- SEARCH_CLASSES,
SEARCH_WEBSITE,
HELP_SEARCH_FIND,
HELP_SEARCH_FIND_NEXT,
@@ -200,7 +200,6 @@ class ScriptEditor : public PanelContainer {
Button *help_search;
Button *site_search;
- Button *class_search;
EditorHelpSearch *help_search_dialog;
ItemList *script_list;
@@ -254,7 +253,7 @@ class ScriptEditor : public PanelContainer {
Vector<ScriptHistory> history;
int history_pos;
- EditorHelpIndex *help_index;
+ Vector<String> previous_scripts;
void _tab_changed(int p_which);
void _menu_option(int p_option);
diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp
index c3e2aa86f0..e6bb8b24a9 100644
--- a/editor/plugins/script_text_editor.cpp
+++ b/editor/plugins/script_text_editor.cpp
@@ -443,6 +443,7 @@ void ScriptTextEditor::_validate_script() {
if (!script->get_language()->validate(text, line, col, errortxt, script->get_path(), &fnc, &warnings, &safe_lines)) {
String error_text = "error(" + itos(line) + "," + itos(col) + "): " + errortxt;
code_editor->set_error(error_text);
+ code_editor->set_error_pos(line - 1, col - 1);
} else {
code_editor->set_error("");
line = -1;
@@ -1049,7 +1050,7 @@ void ScriptTextEditor::_edit_option(int p_op) {
if (text == "")
text = tx->get_word_under_cursor();
if (text != "") {
- emit_signal("request_help_search", text);
+ emit_signal("request_help", text);
}
} break;
case LOOKUP_SYMBOL: {
diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp
index 638de1b213..6bc5c77df2 100644
--- a/editor/plugins/shader_editor_plugin.cpp
+++ b/editor/plugins/shader_editor_plugin.cpp
@@ -193,6 +193,7 @@ void ShaderTextEditor::_validate_script() {
if (err != OK) {
String error_text = "error(" + itos(sl.get_error_line()) + "): " + sl.get_error_text();
set_error(error_text);
+ set_error_pos(sl.get_error_line() - 1, 0);
for (int i = 0; i < get_text_edit()->get_line_count(); i++)
get_text_edit()->set_line_as_marked(i, false);
get_text_edit()->set_line_as_marked(sl.get_error_line() - 1, true);
diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp
index 5566a5aea5..a5563c0497 100644
--- a/editor/plugins/spatial_editor_plugin.cpp
+++ b/editor/plugins/spatial_editor_plugin.cpp
@@ -4204,10 +4204,10 @@ void SpatialEditor::set_state(const Dictionary &p_state) {
gizmo_plugins.write[j]->set_state(state);
switch (state) {
- case EditorSpatialGizmoPlugin::ON_TOP:
+ case EditorSpatialGizmoPlugin::VISIBLE:
gizmos_menu->set_item_icon(idx, gizmos_menu->get_icon("visibility_visible"));
break;
- case EditorSpatialGizmoPlugin::VISIBLE:
+ case EditorSpatialGizmoPlugin::ON_TOP:
gizmos_menu->set_item_icon(idx, gizmos_menu->get_icon("visibility_xray"));
break;
case EditorSpatialGizmoPlugin::HIDDEN:
@@ -4317,10 +4317,10 @@ void SpatialEditor::_menu_gizmo_toggled(int p_option) {
// Change icon
const int state = gizmos_menu->get_item_state(idx);
switch (state) {
- case EditorSpatialGizmoPlugin::ON_TOP:
+ case EditorSpatialGizmoPlugin::VISIBLE:
gizmos_menu->set_item_icon(idx, view_menu->get_popup()->get_icon("visibility_visible"));
break;
- case EditorSpatialGizmoPlugin::VISIBLE:
+ case EditorSpatialGizmoPlugin::ON_TOP:
gizmos_menu->set_item_icon(idx, view_menu->get_popup()->get_icon("visibility_xray"));
break;
case EditorSpatialGizmoPlugin::HIDDEN:
@@ -4839,7 +4839,7 @@ void SpatialEditor::_init_gizmos_menu() {
for (int i = 0; i < gizmo_plugins.size(); ++i) {
if (!gizmo_plugins[i]->can_be_hidden()) continue;
String plugin_name = gizmo_plugins[i]->get_name();
- gizmos_menu->add_multistate_item(TTR(plugin_name), 3, EditorSpatialGizmoPlugin::ON_TOP, i);
+ gizmos_menu->add_multistate_item(TTR(plugin_name), 3, EditorSpatialGizmoPlugin::VISIBLE, i);
gizmos_menu->set_item_icon(gizmos_menu->get_item_index(i), gizmos_menu->get_icon("visibility_visible"));
}
}
@@ -5919,7 +5919,7 @@ void EditorSpatialGizmoPlugin::unregister_gizmo(EditorSpatialGizmo *p_gizmo) {
}
EditorSpatialGizmoPlugin::EditorSpatialGizmoPlugin() {
- current_state = ON_TOP;
+ current_state = VISIBLE;
}
EditorSpatialGizmoPlugin::~EditorSpatialGizmoPlugin() {
diff --git a/editor/plugins/spatial_editor_plugin.h b/editor/plugins/spatial_editor_plugin.h
index 3cce76cc17..c515a4aaf9 100644
--- a/editor/plugins/spatial_editor_plugin.h
+++ b/editor/plugins/spatial_editor_plugin.h
@@ -754,9 +754,9 @@ class EditorSpatialGizmoPlugin : public Resource {
GDCLASS(EditorSpatialGizmoPlugin, Resource);
public:
- static const int ON_TOP = 0;
- static const int VISIBLE = 1;
- static const int HIDDEN = 2;
+ static const int VISIBLE = 0;
+ static const int HIDDEN = 1;
+ static const int ON_TOP = 2;
private:
int current_state;
diff --git a/editor/script_editor_debugger.cpp b/editor/script_editor_debugger.cpp
index faa561ad54..559ab32505 100644
--- a/editor/script_editor_debugger.cpp
+++ b/editor/script_editor_debugger.cpp
@@ -602,6 +602,7 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
String n = p_data[ofs + i * 2 + 0];
Variant v = p_data[ofs + i * 2 + 1];
+
PropertyHint h = PROPERTY_HINT_NONE;
String hs = String();
diff --git a/gles_builders.py b/gles_builders.py
index f9fd6d3fa2..e56ccc4431 100644
--- a/gles_builders.py
+++ b/gles_builders.py
@@ -231,9 +231,9 @@ def build_legacygl_header(filename, include, class_suffix, output_attribs, gles2
fd.write("\t_FORCE_INLINE_ void set_conditional(Conditionals p_conditional,bool p_enable) { _set_conditional(p_conditional,p_enable); }\n\n")
fd.write("\t#ifdef DEBUG_ENABLED\n ")
fd.write("\t#define _FU if (get_uniform(p_uniform)<0) return; if (!is_version_valid()) return; ERR_FAIL_COND( get_active()!=this ); \n\n ")
- fd.write("\t#else\n ")
+ fd.write("\t#else\n ")
fd.write("\t#define _FU if (get_uniform(p_uniform)<0) return; \n\n ")
- fd.write("\t#endif\n")
+ fd.write("\t#endif\n")
fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, float p_value) { _FU glUniform1f(get_uniform(p_uniform),p_value); }\n\n")
fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, double p_value) { _FU glUniform1f(get_uniform(p_uniform),p_value); }\n\n")
fd.write("\t_FORCE_INLINE_ void set_uniform(Uniforms p_uniform, uint8_t p_value) { _FU glUniform1i(get_uniform(p_uniform),p_value); }\n\n")
diff --git a/methods.py b/methods.py
index 111a2347be..5fcbc94298 100644
--- a/methods.py
+++ b/methods.py
@@ -591,7 +591,7 @@ def generate_vs_project(env, num_jobs):
release_debug_targets = ['bin\\godot.windows.opt.tools.32.exe'] + ['bin\\godot.windows.opt.tools.64.exe']
targets = debug_targets + release_targets + release_debug_targets
if not env.get('MSVS'):
- env['MSVS']['PROJECTSUFFIX'] = '.vcxproj'
+ env['MSVS']['PROJECTSUFFIX'] = '.vcxproj'
env['MSVS']['SOLUTIONSUFFIX'] = '.sln'
env.MSVSProject(
target=['#godot' + env['MSVSPROJECTSUFFIX']],
@@ -628,3 +628,27 @@ def CommandNoCache(env, target, sources, command, **args):
result = env.Command(target, sources, command, **args)
env.NoCache(result)
return result
+
+def detect_darwin_sdk_path(platform, env):
+ sdk_name = ''
+ if platform == 'osx':
+ sdk_name = 'macosx'
+ var_name = 'MACOS_SDK_PATH'
+ elif platform == 'iphone':
+ sdk_name = 'iphoneos'
+ var_name = 'IPHONESDK'
+ elif platform == 'iphonesimulator':
+ sdk_name = 'iphonesimulator'
+ var_name = 'IPHONESDK'
+ else:
+ raise Exception("Invalid platform argument passed to detect_darwin_sdk_path")
+
+ if not env[var_name]:
+ try:
+ sdk_path = subprocess.check_output(['xcrun', '--sdk', sdk_name, '--show-sdk-path']).strip()
+ if sdk_path:
+ env[var_name] = sdk_path
+ except (subprocess.CalledProcessError, OSError) as e:
+ print("Failed to find SDK path while running xcrun --sdk {} --show-sdk-path.".format(sdk_name))
+ raise
+
diff --git a/modules/bullet/rigid_body_bullet.cpp b/modules/bullet/rigid_body_bullet.cpp
index 85659e1523..9dd04100ed 100644
--- a/modules/bullet/rigid_body_bullet.cpp
+++ b/modules/bullet/rigid_body_bullet.cpp
@@ -268,6 +268,7 @@ RigidBodyBullet::RigidBodyBullet() :
can_integrate_forces(false),
maxCollisionsDetection(0),
collisionsCount(0),
+ prev_collision_count(0),
maxAreasWhereIam(10),
areaWhereIamCount(0),
countGravityPointSpaces(0),
@@ -293,6 +294,9 @@ RigidBodyBullet::RigidBodyBullet() :
areasWhereIam.write[i] = NULL;
}
btBody->setSleepingThresholds(0.2, 0.2);
+
+ prev_collision_traces = &collision_traces_1;
+ curr_collision_traces = &collision_traces_2;
}
RigidBodyBullet::~RigidBodyBullet() {
@@ -410,7 +414,14 @@ void RigidBodyBullet::on_collision_filters_change() {
}
void RigidBodyBullet::on_collision_checker_start() {
+
+ prev_collision_count = collisionsCount;
collisionsCount = 0;
+
+ // Swap array
+ Vector<RigidBodyBullet *> *s = prev_collision_traces;
+ prev_collision_traces = curr_collision_traces;
+ curr_collision_traces = s;
}
void RigidBodyBullet::on_collision_checker_end() {
@@ -433,10 +444,20 @@ bool RigidBodyBullet::add_collision_object(RigidBodyBullet *p_otherObject, const
cd.other_object_shape = p_other_shape_index;
cd.local_shape = p_local_shape_index;
+ curr_collision_traces->write[collisionsCount] = p_otherObject;
+
++collisionsCount;
return true;
}
+bool RigidBodyBullet::was_colliding(RigidBodyBullet *p_other_object) {
+ for (int i = prev_collision_count - 1; 0 <= i; --i) {
+ if ((*prev_collision_traces)[i] == p_other_object)
+ return true;
+ }
+ return false;
+}
+
void RigidBodyBullet::assert_no_constraints() {
if (btBody->getNumConstraintRefs()) {
WARN_PRINT("A body with a joints is destroyed. Please check the implementation in order to destroy the joint before the body.");
diff --git a/modules/bullet/rigid_body_bullet.h b/modules/bullet/rigid_body_bullet.h
index 26e5018c87..0696073d21 100644
--- a/modules/bullet/rigid_body_bullet.h
+++ b/modules/bullet/rigid_body_bullet.h
@@ -205,9 +205,15 @@ private:
bool can_integrate_forces;
Vector<CollisionData> collisions;
+ Vector<RigidBodyBullet *> collision_traces_1;
+ Vector<RigidBodyBullet *> collision_traces_2;
+ Vector<RigidBodyBullet *> *prev_collision_traces;
+ Vector<RigidBodyBullet *> *curr_collision_traces;
+
// these parameters are used to avoid vector resize
int maxCollisionsDetection;
int collisionsCount;
+ int prev_collision_count;
Vector<AreaBullet *> areasWhereIam;
// these parameters are used to avoid vector resize
@@ -244,9 +250,17 @@ public:
virtual void on_collision_checker_end();
void set_max_collisions_detection(int p_maxCollisionsDetection) {
+
+ ERR_FAIL_COND(0 > p_maxCollisionsDetection);
+
maxCollisionsDetection = p_maxCollisionsDetection;
+
collisions.resize(p_maxCollisionsDetection);
+ collision_traces_1.resize(p_maxCollisionsDetection);
+ collision_traces_2.resize(p_maxCollisionsDetection);
+
collisionsCount = 0;
+ prev_collision_count = MIN(prev_collision_count, p_maxCollisionsDetection);
}
int get_max_collisions_detection() {
return maxCollisionsDetection;
@@ -254,6 +268,7 @@ public:
bool can_add_collision() { return collisionsCount < maxCollisionsDetection; }
bool add_collision_object(RigidBodyBullet *p_otherObject, const Vector3 &p_hitWorldLocation, const Vector3 &p_hitLocalLocation, const Vector3 &p_hitNormal, const float &p_appliedImpulse, int p_other_shape_index, int p_local_shape_index);
+ bool was_colliding(RigidBodyBullet *p_other_object);
void assert_no_constraints();
diff --git a/modules/bullet/space_bullet.cpp b/modules/bullet/space_bullet.cpp
index ab2d1781ad..fed12cd5ed 100644
--- a/modules/bullet/space_bullet.cpp
+++ b/modules/bullet/space_bullet.cpp
@@ -786,16 +786,22 @@ void SpaceBullet::check_body_collision() {
}
const int numContacts = contactManifold->getNumContacts();
+
+ /// Since I don't need report all contacts for these objects,
+ /// So report only the first
#define REPORT_ALL_CONTACTS 0
#if REPORT_ALL_CONTACTS
for (int j = 0; j < numContacts; j++) {
btManifoldPoint &pt = contactManifold->getContactPoint(j);
#else
- // Since I don't need report all contacts for these objects, I'll report only the first
if (numContacts) {
btManifoldPoint &pt = contactManifold->getContactPoint(0);
#endif
- if (pt.getDistance() <= 0.0) {
+ if (
+ pt.getDistance() <= 0.0 ||
+ bodyA->was_colliding(bodyB) ||
+ bodyB->was_colliding(bodyA)) {
+
Vector3 collisionWorldPosition;
Vector3 collisionLocalPosition;
Vector3 normalOnB;
diff --git a/modules/csg/csg_shape.cpp b/modules/csg/csg_shape.cpp
index 23d879e1cd..a4c34e7583 100644
--- a/modules/csg/csg_shape.cpp
+++ b/modules/csg/csg_shape.cpp
@@ -201,10 +201,9 @@ void CSGShape::mikktSetTSpaceBasic(const SMikkTSpaceContext *pContext, const flo
int i = (iFace * 3 + iVert) * 4;
- // Godot seems to want the tangent flipped because our handedness is reversed..
- surface.tansw[i++] = -fvTangent[0];
- surface.tansw[i++] = -fvTangent[1];
- surface.tansw[i++] = -fvTangent[2];
+ surface.tansw[i++] = fvTangent[0];
+ surface.tansw[i++] = fvTangent[1];
+ surface.tansw[i++] = fvTangent[2];
surface.tansw[i++] = fSign;
}
@@ -219,11 +218,10 @@ void CSGShape::mikktSetTSpaceDefault(const SMikkTSpaceContext *pContext, const f
Vector3 bitangent = Vector3(fvBiTangent[0], fvBiTangent[1], fvBiTangent[2]);
float d = bitangent.dot(normal.cross(tangent));
- // Godot seems to want the tangent flipped because our handedness is reversed..
i *= 4;
- surface.tansw[i++] = -tangent.x;
- surface.tansw[i++] = -tangent.y;
- surface.tansw[i++] = -tangent.z;
+ surface.tansw[i++] = tangent.x;
+ surface.tansw[i++] = tangent.y;
+ surface.tansw[i++] = tangent.z;
surface.tansw[i++] = d < 0 ? -1 : 1;
}
@@ -1666,6 +1664,24 @@ CSGBrush *CSGPolygon::_build_brush() {
Path *path = NULL;
Ref<Curve3D> curve;
+ // get bounds for our polygon
+ Vector2 final_polygon_min;
+ Vector2 final_polygon_max;
+ for (int i = 0; i < final_polygon.size(); i++) {
+ Vector2 p = final_polygon[i];
+ if (i == 0) {
+ final_polygon_min = p;
+ final_polygon_max = final_polygon_min;
+ } else {
+ if (p.x < final_polygon_min.x) final_polygon_min.x = p.x;
+ if (p.y < final_polygon_min.y) final_polygon_min.y = p.y;
+
+ if (p.x > final_polygon_max.x) final_polygon_max.x = p.x;
+ if (p.y > final_polygon_max.y) final_polygon_max.y = p.y;
+ }
+ }
+ Vector2 final_polygon_size = final_polygon_max - final_polygon_min;
+
if (mode == MODE_PATH) {
if (!has_node(path_node))
return NULL;
@@ -1757,6 +1773,10 @@ CSGBrush *CSGPolygon::_build_brush() {
v.z -= depth;
}
facesw[face * 3 + k] = v;
+ uvsw[face * 3 + k] = (p - final_polygon_min) / final_polygon_size;
+ if (i == 0) {
+ uvsw[face * 3 + k].x = 1.0 - uvsw[face * 3 + k].x; /* flip x */
+ }
}
smoothw[face] = false;
@@ -1888,6 +1908,7 @@ CSGBrush *CSGPolygon::_build_brush() {
Vector2 p = final_polygon[triangles[j + src[k]]];
Vector3 v = Vector3(p.x, p.y, 0);
facesw[face * 3 + k] = v;
+ uvsw[face * 3 + k] = (p - final_polygon_min) / final_polygon_size;
}
smoothw[face] = false;
@@ -1905,6 +1926,8 @@ CSGBrush *CSGPolygon::_build_brush() {
Vector2 p = final_polygon[triangles[j + src[k]]];
Vector3 v = Vector3(normali_n.x * p.x, p.y, normali_n.z * p.x);
facesw[face * 3 + k] = v;
+ uvsw[face * 3 + k] = (p - final_polygon_min) / final_polygon_size;
+ uvsw[face * 3 + k].x = 1.0 - uvsw[face * 3 + k].x; /* flip x */
}
smoothw[face] = false;
@@ -1990,10 +2013,10 @@ CSGBrush *CSGPolygon::_build_brush() {
};
Vector2 u[4] = {
- Vector2(u1, 0),
Vector2(u1, 1),
- Vector2(u2, 1),
- Vector2(u2, 0)
+ Vector2(u1, 0),
+ Vector2(u2, 0),
+ Vector2(u2, 1)
};
// face 1
@@ -2036,6 +2059,7 @@ CSGBrush *CSGPolygon::_build_brush() {
Vector2 p = final_polygon[triangles[j + src[k]]];
Vector3 v = Vector3(p.x, p.y, 0);
facesw[face * 3 + k] = xf.xform(v);
+ uvsw[face * 3 + k] = (p - final_polygon_min) / final_polygon_size;
}
smoothw[face] = false;
@@ -2053,6 +2077,8 @@ CSGBrush *CSGPolygon::_build_brush() {
Vector2 p = final_polygon[triangles[j + src[k]]];
Vector3 v = Vector3(p.x, p.y, 0);
facesw[face * 3 + k] = xf.xform(v);
+ uvsw[face * 3 + k] = (p - final_polygon_min) / final_polygon_size;
+ uvsw[face * 3 + k].x = 1.0 - uvsw[face * 3 + k].x; /* flip x */
}
smoothw[face] = false;
@@ -2077,6 +2103,9 @@ CSGBrush *CSGPolygon::_build_brush() {
} else {
aabb.expand_to(facesw[i]);
}
+
+ // invert UVs on the Y-axis OpenGL = upside down
+ uvsw[i].y = 1.0 - uvsw[i].y;
}
}
diff --git a/modules/gdnative/gdnative_builders.py b/modules/gdnative/gdnative_builders.py
index f9d1ed9dc5..ff18a3ae69 100644
--- a/modules/gdnative/gdnative_builders.py
+++ b/modules/gdnative/gdnative_builders.py
@@ -87,20 +87,20 @@ def _build_gdnative_api_struct_header(api):
ret_val = []
if core['next']:
ret_val += generate_core_extension_struct(core['next'])
-
+
ret_val += [
'typedef struct godot_gdnative_core_' + ('{0}_{1}'.format(core['version']['major'], core['version']['minor'])) + '_api_struct {',
'\tunsigned int type;',
'\tgodot_gdnative_api_version version;',
'\tconst godot_gdnative_api_struct *next;',
]
-
+
for funcdef in core['api']:
args = ', '.join(['%s%s' % (_spaced(t), n) for t, n in funcdef['arguments']])
ret_val.append('\t%s(*%s)(%s);' % (_spaced(funcdef['return_type']), funcdef['name'], args))
-
+
ret_val += ['} godot_gdnative_core_' + '{0}_{1}'.format(core['version']['major'], core['version']['minor']) + '_api_struct;', '']
-
+
return ret_val
@@ -171,26 +171,26 @@ def _build_gdnative_api_struct_source(api):
ret_val += ['};\n']
return ret_val
-
-
+
+
def get_core_struct_definition(core):
ret_val = []
-
+
if core['next']:
ret_val += get_core_struct_definition(core['next'])
-
+
ret_val += [
'extern const godot_gdnative_core_' + ('{0}_{1}_api_struct api_{0}_{1}'.format(core['version']['major'], core['version']['minor'])) + ' = {',
'\tGDNATIVE_' + core['type'] + ',',
'\t{' + str(core['version']['major']) + ', ' + str(core['version']['minor']) + '},',
'\t' + ('NULL' if not core['next'] else ('(const godot_gdnative_api_struct *)& api_{0}_{1}'.format(core['version']['major'], core['version']['minor']))) + ','
]
-
+
for funcdef in core['api']:
ret_val.append('\t%s,' % funcdef['name'])
-
+
ret_val += ['};\n']
-
+
return ret_val
for ext in api['extensions']:
@@ -204,7 +204,7 @@ def _build_gdnative_api_struct_source(api):
out += ['\t(godot_gdnative_api_struct *)&api_extension_' + name + '_struct,']
out += ['};\n']
-
+
if api['core']['next']:
out += get_core_struct_definition(api['core']['next'])
diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp
index 159085df34..1f5f5035f9 100644
--- a/modules/gdscript/gdscript.cpp
+++ b/modules/gdscript/gdscript.cpp
@@ -421,31 +421,40 @@ bool GDScript::_update_exports() {
base_cache = Ref<GDScript>();
}
- if (c->extends_used && String(c->extends_file) != "" && String(c->extends_file) != get_path()) {
-
- String path = c->extends_file;
- if (path.is_rel_path()) {
-
- String base = get_path();
- if (base == "" || base.is_rel_path()) {
-
- ERR_PRINT(("Could not resolve relative path for parent class: " + path).utf8().get_data());
- } else {
- path = base.get_base_dir().plus_file(path);
+ if (c->extends_used) {
+ String path = "";
+ if (String(c->extends_file) != "" && String(c->extends_file) != get_path()) {
+ path = c->extends_file;
+ if (path.is_rel_path()) {
+
+ String base = get_path();
+ if (base == "" || base.is_rel_path()) {
+
+ ERR_PRINT(("Could not resolve relative path for parent class: " + path).utf8().get_data());
+ } else {
+ path = base.get_base_dir().plus_file(path);
+ }
}
+ } else if (c->extends_class.size() != 0) {
+ String base = c->extends_class[0];
+
+ if (ScriptServer::is_global_class(base))
+ path = ScriptServer::get_global_class_path(base);
}
- if (path != get_path()) {
+ if (path != "") {
+ if (path != get_path()) {
- Ref<GDScript> bf = ResourceLoader::load(path);
+ Ref<GDScript> bf = ResourceLoader::load(path);
- if (bf.is_valid()) {
+ if (bf.is_valid()) {
- base_cache = bf;
- bf->inheriters_cache.insert(get_instance_id());
+ base_cache = bf;
+ bf->inheriters_cache.insert(get_instance_id());
+ }
+ } else {
+ ERR_PRINT(("Path extending itself in " + path).utf8().get_data());
}
- } else {
- ERR_PRINT(("Path extending itself in " + path).utf8().get_data());
}
}
diff --git a/modules/mono/glue/Managed/Files/AABB.cs b/modules/mono/glue/Managed/Files/AABB.cs
index 66490b5e25..33b2b46712 100644
--- a/modules/mono/glue/Managed/Files/AABB.cs
+++ b/modules/mono/glue/Managed/Files/AABB.cs
@@ -407,8 +407,8 @@ namespace Godot
return new AABB(min, max - min);
}
-
- // Constructors
+
+ // Constructors
public AABB(Vector3 position, Vector3 size)
{
_position = position;
diff --git a/modules/mono/glue/Managed/Files/Basis.cs b/modules/mono/glue/Managed/Files/Basis.cs
index a5618cb28d..b318d96bb9 100644
--- a/modules/mono/glue/Managed/Files/Basis.cs
+++ b/modules/mono/glue/Managed/Files/Basis.cs
@@ -13,9 +13,9 @@ namespace Godot
{
private static readonly Basis identity = new Basis
(
- new Vector3(1f, 0f, 0f),
- new Vector3(0f, 1f, 0f),
- new Vector3(0f, 0f, 1f)
+ 1f, 0f, 0f,
+ 0f, 1f, 0f,
+ 0f, 0f, 1f
);
private static readonly Basis[] orthoBases = {
@@ -159,9 +159,9 @@ namespace Godot
{
return new Basis
(
- new Vector3(xAxis.x, yAxis.x, zAxis.x),
- new Vector3(xAxis.y, yAxis.y, zAxis.y),
- new Vector3(xAxis.z, yAxis.z, zAxis.z)
+ xAxis.x, yAxis.x, zAxis.x,
+ xAxis.y, yAxis.y, zAxis.y,
+ xAxis.z, yAxis.z, zAxis.z
);
}
@@ -410,10 +410,12 @@ namespace Godot
);
}
- public Quat Quat() {
+ public Quat Quat()
+ {
real_t trace = _x[0] + _y[1] + _z[2];
- if (trace > 0.0f) {
+ if (trace > 0.0f)
+ {
real_t s = Mathf.Sqrt(trace + 1.0f) * 2f;
real_t inv_s = 1f / s;
return new Quat(
@@ -424,7 +426,8 @@ namespace Godot
);
}
- if (_x[0] > _y[1] && _x[0] > _z[2]) {
+ if (_x[0] > _y[1] && _x[0] > _z[2])
+ {
real_t s = Mathf.Sqrt(_x[0] - _y[1] - _z[2] + 1.0f) * 2f;
real_t inv_s = 1f / s;
return new Quat(
@@ -435,7 +438,8 @@ namespace Godot
);
}
- if (_y[1] > _z[2]) {
+ if (_y[1] > _z[2])
+ {
real_t s = Mathf.Sqrt(-_x[0] + _y[1] - _z[2] + 1.0f) * 2f;
real_t inv_s = 1f / s;
return new Quat(
@@ -444,7 +448,9 @@ namespace Godot
(_y[2] + _z[1]) * inv_s,
(_x[2] - _z[0]) * inv_s
);
- } else {
+ }
+ else
+ {
real_t s = Mathf.Sqrt(-_x[0] - _y[1] + _z[2] + 1.0f) * 2f;
real_t inv_s = 1f / s;
return new Quat(
@@ -502,8 +508,8 @@ namespace Godot
{
var axis_sq = new Vector3(axis.x * axis.x, axis.y * axis.y, axis.z * axis.z);
- real_t cosine = Mathf.Cos( phi);
- real_t sine = Mathf.Sin( phi);
+ real_t cosine = Mathf.Cos(phi);
+ real_t sine = Mathf.Sin(phi);
_x = new Vector3
(
@@ -529,12 +535,17 @@ namespace Godot
public Basis(Vector3 xAxis, Vector3 yAxis, Vector3 zAxis)
{
- _x = xAxis;
- _y = yAxis;
- _z = zAxis;
+ _x = new Vector3(xAxis.x, yAxis.x, zAxis.x);
+ _y = new Vector3(xAxis.y, yAxis.y, zAxis.y);
+ _z = new Vector3(xAxis.z, yAxis.z, zAxis.z);
+ // Same as:
+ // SetAxis(0, xAxis);
+ // SetAxis(1, yAxis);
+ // SetAxis(2, zAxis);
+ // We need to assign the struct fields so we can't do that...
}
- public Basis(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz)
+ internal Basis(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz)
{
_x = new Vector3(xx, xy, xz);
_y = new Vector3(yx, yy, yz);
diff --git a/modules/mono/glue/Managed/Files/Color.cs b/modules/mono/glue/Managed/Files/Color.cs
index 88cb8524b8..fc5bb010a9 100644
--- a/modules/mono/glue/Managed/Files/Color.cs
+++ b/modules/mono/glue/Managed/Files/Color.cs
@@ -379,8 +379,8 @@ namespace Godot
return txt;
}
-
- // Constructors
+
+ // Constructors
public Color(float r, float g, float b, float a = 1.0f)
{
this.r = r;
diff --git a/modules/mono/glue/Managed/Files/Mathf.cs b/modules/mono/glue/Managed/Files/Mathf.cs
index a89dfe5f27..dcab3c1ffc 100644
--- a/modules/mono/glue/Managed/Files/Mathf.cs
+++ b/modules/mono/glue/Managed/Files/Mathf.cs
@@ -206,7 +206,7 @@ namespace Godot
public static real_t PosMod(real_t a, real_t b)
{
real_t c = a % b;
- if ((c < 0 && b > 0) || (c > 0 && b < 0))
+ if ((c < 0 && b > 0) || (c > 0 && b < 0))
{
c += b;
}
@@ -219,7 +219,7 @@ namespace Godot
public static int PosMod(int a, int b)
{
int c = a % b;
- if ((c < 0 && b > 0) || (c > 0 && b < 0))
+ if ((c < 0 && b > 0) || (c > 0 && b < 0))
{
c += b;
}
diff --git a/modules/mono/glue/Managed/Files/MathfEx.cs b/modules/mono/glue/Managed/Files/MathfEx.cs
index 739b7fb568..2ef02cc288 100644
--- a/modules/mono/glue/Managed/Files/MathfEx.cs
+++ b/modules/mono/glue/Managed/Files/MathfEx.cs
@@ -29,7 +29,7 @@ namespace Godot
public static int FloorToInt(real_t s)
{
return (int)Math.Floor(s);
- }
+ }
public static int RoundToInt(real_t s)
{
diff --git a/modules/mono/glue/Managed/Files/Plane.cs b/modules/mono/glue/Managed/Files/Plane.cs
index 9611dce11e..f11cd490a9 100644
--- a/modules/mono/glue/Managed/Files/Plane.cs
+++ b/modules/mono/glue/Managed/Files/Plane.cs
@@ -144,7 +144,7 @@ namespace Godot
{
return point - _normal * DistanceTo(point);
}
-
+
// Constants
private static readonly Plane _planeYZ = new Plane(1, 0, 0, 0);
private static readonly Plane _planeXZ = new Plane(0, 1, 0, 0);
@@ -153,8 +153,8 @@ namespace Godot
public static Plane PlaneYZ { get { return _planeYZ; } }
public static Plane PlaneXZ { get { return _planeXZ; } }
public static Plane PlaneXY { get { return _planeXY; } }
-
- // Constructors
+
+ // Constructors
public Plane(real_t a, real_t b, real_t c, real_t d)
{
_normal = new Vector3(a, b, c);
diff --git a/modules/mono/glue/Managed/Files/Quat.cs b/modules/mono/glue/Managed/Files/Quat.cs
index eaa027eb69..fd1ac01083 100644
--- a/modules/mono/glue/Managed/Files/Quat.cs
+++ b/modules/mono/glue/Managed/Files/Quat.cs
@@ -202,7 +202,7 @@ namespace Godot
// Static Readonly Properties
public static Quat Identity { get; } = new Quat(0f, 0f, 0f, 1f);
- // Constructors
+ // Constructors
public Quat(real_t x, real_t y, real_t z, real_t w)
{
this.x = x;
diff --git a/modules/mono/glue/Managed/Files/Rect2.cs b/modules/mono/glue/Managed/Files/Rect2.cs
index cb25c267bc..888f300347 100644
--- a/modules/mono/glue/Managed/Files/Rect2.cs
+++ b/modules/mono/glue/Managed/Files/Rect2.cs
@@ -182,8 +182,8 @@ namespace Godot
return newRect;
}
-
- // Constructors
+
+ // Constructors
public Rect2(Vector2 position, Vector2 size)
{
_position = position;
diff --git a/modules/mono/glue/Managed/Files/StringExtensions.cs b/modules/mono/glue/Managed/Files/StringExtensions.cs
index 21c9be98c1..c194facd0b 100644
--- a/modules/mono/glue/Managed/Files/StringExtensions.cs
+++ b/modules/mono/glue/Managed/Files/StringExtensions.cs
@@ -185,7 +185,7 @@ namespace Godot
int instanceIndex = 0;
int toIndex = 0;
-
+
if (caseSensitive) // Outside while loop to avoid checking multiple times, despite some code duplication.
{
while (true)
@@ -480,9 +480,9 @@ namespace Godot
return false; // Don't start with number plz
}
- bool validChar = instance[i] >= '0' &&
- instance[i] <= '9' || instance[i] >= 'a' &&
- instance[i] <= 'z' || instance[i] >= 'A' &&
+ bool validChar = instance[i] >= '0' &&
+ instance[i] <= '9' || instance[i] >= 'a' &&
+ instance[i] <= 'z' || instance[i] >= 'A' &&
instance[i] <= 'Z' || instance[i] == '_';
if (!validChar)
diff --git a/modules/mono/glue/Managed/Files/Transform.cs b/modules/mono/glue/Managed/Files/Transform.cs
index 068007d7f0..fa85855edd 100644
--- a/modules/mono/glue/Managed/Files/Transform.cs
+++ b/modules/mono/glue/Managed/Files/Transform.cs
@@ -124,16 +124,16 @@ namespace Godot
// Constants
private static readonly Transform _identity = new Transform(Basis.Identity, Vector3.Zero);
- private static readonly Transform _flipX = new Transform(new Basis(new Vector3(-1, 0, 0), new Vector3(0, 1, 0), new Vector3(0, 0, 1)), Vector3.Zero);
- private static readonly Transform _flipY = new Transform(new Basis(new Vector3(1, 0, 0), new Vector3(0, -1, 0), new Vector3(0, 0, 1)), Vector3.Zero);
- private static readonly Transform _flipZ = new Transform(new Basis(new Vector3(1, 0, 0), new Vector3(0, 1, 0), new Vector3(0, 0, -1)), Vector3.Zero);
+ private static readonly Transform _flipX = new Transform(new Basis(-1, 0, 0, 0, 1, 0, 0, 0, 1), Vector3.Zero);
+ private static readonly Transform _flipY = new Transform(new Basis(1, 0, 0, 0, -1, 0, 0, 0, 1), Vector3.Zero);
+ private static readonly Transform _flipZ = new Transform(new Basis(1, 0, 0, 0, 1, 0, 0, 0, -1), Vector3.Zero);
public static Transform Identity { get { return _identity; } }
public static Transform FlipX { get { return _flipX; } }
public static Transform FlipY { get { return _flipY; } }
public static Transform FlipZ { get { return _flipZ; } }
- // Constructors
+ // Constructors
public Transform(Vector3 xAxis, Vector3 yAxis, Vector3 zAxis, Vector3 origin)
{
basis = Basis.CreateFromAxes(xAxis, yAxis, zAxis);
diff --git a/modules/mono/glue/Managed/Files/Transform2D.cs b/modules/mono/glue/Managed/Files/Transform2D.cs
index 8d30833066..c9e5b560b2 100644
--- a/modules/mono/glue/Managed/Files/Transform2D.cs
+++ b/modules/mono/glue/Managed/Files/Transform2D.cs
@@ -261,15 +261,15 @@ namespace Godot
public static Transform2D Identity { get { return _identity; } }
public static Transform2D FlipX { get { return _flipX; } }
public static Transform2D FlipY { get { return _flipY; } }
-
- // Constructors
+
+ // Constructors
public Transform2D(Vector2 xAxis, Vector2 yAxis, Vector2 origin)
{
x = xAxis;
y = yAxis;
o = origin;
}
-
+
public Transform2D(real_t xx, real_t xy, real_t yx, real_t yy, real_t ox, real_t oy)
{
x = new Vector2(xx, xy);
diff --git a/modules/mono/glue/Managed/Files/Vector2.cs b/modules/mono/glue/Managed/Files/Vector2.cs
index 080b8802ba..ce41886bfc 100644
--- a/modules/mono/glue/Managed/Files/Vector2.cs
+++ b/modules/mono/glue/Managed/Files/Vector2.cs
@@ -215,7 +215,7 @@ namespace Godot
x = v.x;
y = v.y;
}
-
+
public Vector2 Slerp(Vector2 b, real_t t)
{
real_t theta = AngleTo(b);
@@ -242,7 +242,7 @@ namespace Godot
private static readonly Vector2 _one = new Vector2(1, 1);
private static readonly Vector2 _negOne = new Vector2(-1, -1);
private static readonly Vector2 _inf = new Vector2(Mathf.Inf, Mathf.Inf);
-
+
private static readonly Vector2 _up = new Vector2(0, -1);
private static readonly Vector2 _down = new Vector2(0, 1);
private static readonly Vector2 _right = new Vector2(1, 0);
diff --git a/modules/mono/glue/Managed/Files/Vector3.cs b/modules/mono/glue/Managed/Files/Vector3.cs
index 6fffe5e4d6..f6ff27989d 100644
--- a/modules/mono/glue/Managed/Files/Vector3.cs
+++ b/modules/mono/glue/Managed/Files/Vector3.cs
@@ -204,9 +204,9 @@ namespace Godot
public Basis Outer(Vector3 b)
{
return new Basis(
- new Vector3(x * b.x, x * b.y, x * b.z),
- new Vector3(y * b.x, y * b.y, y * b.z),
- new Vector3(z * b.x, z * b.y, z * b.z)
+ x * b.x, x * b.y, x * b.z,
+ y * b.x, y * b.y, y * b.z,
+ z * b.x, z * b.y, z * b.z
);
}
@@ -276,13 +276,13 @@ namespace Godot
0f, 0f, z
);
}
-
+
// Constants
private static readonly Vector3 _zero = new Vector3(0, 0, 0);
private static readonly Vector3 _one = new Vector3(1, 1, 1);
private static readonly Vector3 _negOne = new Vector3(-1, -1, -1);
private static readonly Vector3 _inf = new Vector3(Mathf.Inf, Mathf.Inf, Mathf.Inf);
-
+
private static readonly Vector3 _up = new Vector3(0, 1, 0);
private static readonly Vector3 _down = new Vector3(0, -1, 0);
private static readonly Vector3 _right = new Vector3(1, 0, 0);
@@ -294,7 +294,7 @@ namespace Godot
public static Vector3 One { get { return _one; } }
public static Vector3 NegOne { get { return _negOne; } }
public static Vector3 Inf { get { return _inf; } }
-
+
public static Vector3 Up { get { return _up; } }
public static Vector3 Down { get { return _down; } }
public static Vector3 Right { get { return _right; } }
diff --git a/modules/mono/glue/Managed/Properties/AssemblyInfo.cs b/modules/mono/glue/Managed/Properties/AssemblyInfo.cs
index 7ed68acad7..77b3774e81 100644
--- a/modules/mono/glue/Managed/Properties/AssemblyInfo.cs
+++ b/modules/mono/glue/Managed/Properties/AssemblyInfo.cs
@@ -1,7 +1,7 @@
using System.Reflection;
using System.Runtime.CompilerServices;
-// Information about this assembly is defined by the following attributes.
+// Information about this assembly is defined by the following attributes.
// Change them to the values specific to your project.
[assembly: AssemblyTitle("Managed")]
@@ -19,7 +19,7 @@ using System.Runtime.CompilerServices;
[assembly: AssemblyVersion("1.0.*")]
-// The following attributes are used to specify the signing key for the assembly,
+// The following attributes are used to specify the signing key for the assembly,
// if desired. See the Mono documentation for more information about signing.
//[assembly: AssemblyDelaySign(false)]
diff --git a/modules/visual_script/doc_classes/VisualScriptCustomNode.xml b/modules/visual_script/doc_classes/VisualScriptCustomNode.xml
index b8e77a1b0f..ff3ed66e81 100644
--- a/modules/visual_script/doc_classes/VisualScriptCustomNode.xml
+++ b/modules/visual_script/doc_classes/VisualScriptCustomNode.xml
@@ -125,12 +125,10 @@
</argument>
<description>
Execute the custom node's logic, returning the index of the output sequence port to use or a [String] when there is an error.
-
The [code]inputs[/code] array contains the values of the input ports.
[code]outputs[/code] is an array whose indices should be set to the respective outputs.
The [code]start_mode[/code] is usually [code]START_MODE_BEGIN_SEQUENCE[/code], unless you have used the STEP_* constants.
[code]working_mem[/code] is an array which can be used to persist information between runs of the custom node.
-
When returning, you can mask the returned value with one of the STEP_* constants.
</description>
</method>
diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp
index c5f2070963..afaa6a9b95 100644
--- a/modules/visual_script/visual_script_editor.cpp
+++ b/modules/visual_script/visual_script_editor.cpp
@@ -1923,7 +1923,7 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da
}
}
-void VisualScriptEditor::_selected_method(const String &p_method, const String &p_type) {
+void VisualScriptEditor::_selected_method(const String &p_method, const String &p_type, const bool p_connecting) {
Ref<VisualScriptFunctionCall> vsfc = script->get_node(edited_func, selecting_method_id);
if (!vsfc.is_valid())
diff --git a/modules/visual_script/visual_script_editor.h b/modules/visual_script/visual_script_editor.h
index ce3245bc28..5f707c9e4c 100644
--- a/modules/visual_script/visual_script_editor.h
+++ b/modules/visual_script/visual_script_editor.h
@@ -234,7 +234,7 @@ class VisualScriptEditor : public ScriptEditorBase {
void _comment_node_resized(const Vector2 &p_new_size, int p_node);
int selecting_method_id;
- void _selected_method(const String &p_method, const String &p_type);
+ void _selected_method(const String &p_method, const String &p_type, const bool p_connecting);
void _draw_color_over_button(Object *obj, Color p_color);
void _button_resource_previewed(const String &p_path, const Ref<Texture> &p_preview, const Ref<Texture> &p_small_preview, Variant p_ud);
diff --git a/platform/android/detect.py b/platform/android/detect.py
index e4cab2fb23..7a728e4ef1 100644
--- a/platform/android/detect.py
+++ b/platform/android/detect.py
@@ -223,7 +223,7 @@ def configure(env):
else:
print("Using NDK deprecated headers")
env.Append(CPPFLAGS=["-isystem", lib_sysroot + "/usr/include"])
-
+
env.Append(CPPFLAGS='-fpic -ffunction-sections -funwind-tables -fstack-protector-strong -fvisibility=hidden -fno-strict-aliasing'.split())
env.Append(CPPFLAGS='-DNO_STATVFS -DGLES_ENABLED'.split())
@@ -267,12 +267,12 @@ def configure(env):
env.Append(LINKFLAGS=['-shared', '--sysroot=' + lib_sysroot, '-Wl,--warn-shared-textrel'])
if mt_link:
env.Append(LINKFLAGS=['-Wl,--threads'])
-
+
if env["android_arch"] == "armv7":
env.Append(LINKFLAGS='-Wl,--fix-cortex-a8'.split())
env.Append(LINKFLAGS='-Wl,--no-undefined -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now'.split())
env.Append(LINKFLAGS='-Wl,-soname,libgodot_android.so -Wl,--gc-sections'.split())
-
+
env.Append(LINKFLAGS=target_opts)
env.Append(LINKFLAGS=common_opts)
diff --git a/platform/android/java/res/layout/status_bar_ongoing_event_progress_bar.xml b/platform/android/java/res/layout/status_bar_ongoing_event_progress_bar.xml
index 23bac02294..104993da7e 100644
--- a/platform/android/java/res/layout/status_bar_ongoing_event_progress_bar.xml
+++ b/platform/android/java/res/layout/status_bar_ongoing_event_progress_bar.xml
@@ -32,9 +32,9 @@
android:id="@+id/appIcon"
android:layout_width="fill_parent"
android:layout_height="25dp"
- android:scaleType="centerInside"
+ android:scaleType="centerInside"
android:layout_alignParentLeft="true"
- android:layout_alignParentTop="true"
+ android:layout_alignParentTop="true"
android:src="@android:drawable/stat_sys_download" />
<TextView
diff --git a/platform/android/java/src/org/godotengine/godot/utils/CustomSSLSocketFactory.java b/platform/android/java/src/org/godotengine/godot/utils/CustomSSLSocketFactory.java
index 7216d8b5a4..03a7a71bb1 100644
--- a/platform/android/java/src/org/godotengine/godot/utils/CustomSSLSocketFactory.java
+++ b/platform/android/java/src/org/godotengine/godot/utils/CustomSSLSocketFactory.java
@@ -44,7 +44,7 @@ import javax.net.ssl.TrustManagerFactory;
import org.apache.http.conn.ssl.SSLSocketFactory;
/**
- *
+ *
* @author Luis Linietsky <luis.linietsky@gmail.com>
*/
public class CustomSSLSocketFactory extends SSLSocketFactory {
diff --git a/platform/android/java/src/org/godotengine/godot/utils/HttpRequester.java b/platform/android/java/src/org/godotengine/godot/utils/HttpRequester.java
index b84f5cce2e..cfe9c4fef0 100644
--- a/platform/android/java/src/org/godotengine/godot/utils/HttpRequester.java
+++ b/platform/android/java/src/org/godotengine/godot/utils/HttpRequester.java
@@ -69,7 +69,7 @@ import android.content.SharedPreferences;
import android.util.Log;
/**
- *
+ *
* @author Luis Linietsky <luis.linietsky@gmail.com>
*/
public class HttpRequester {
diff --git a/platform/android/java/src/org/godotengine/godot/utils/RequestParams.java b/platform/android/java/src/org/godotengine/godot/utils/RequestParams.java
index 2368766afa..a1d5b26b3c 100644
--- a/platform/android/java/src/org/godotengine/godot/utils/RequestParams.java
+++ b/platform/android/java/src/org/godotengine/godot/utils/RequestParams.java
@@ -39,7 +39,7 @@ import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
/**
- *
+ *
* @author Luis Linietsky <luis.linietsky@gmail.com>
*/
public class RequestParams {
diff --git a/platform/android/java_glue.cpp b/platform/android/java_glue.cpp
index 07e4048c12..43bd841baf 100644
--- a/platform/android/java_glue.cpp
+++ b/platform/android/java_glue.cpp
@@ -268,11 +268,11 @@ Variant _jobject_to_variant(JNIEnv *env, jobject obj) {
return ret;
};
- if (name == "java.lang.Integer") {
+ if (name == "java.lang.Integer" || name == "java.lang.Long") {
jclass nclass = env->FindClass("java/lang/Number");
- jmethodID intValue = env->GetMethodID(nclass, "intValue", "()I");
- int ret = env->CallIntMethod(obj, intValue);
+ jmethodID longValue = env->GetMethodID(nclass, "longValue", "()J");
+ jlong ret = env->CallLongMethod(obj, longValue);
return ret;
};
diff --git a/platform/android/power_android.cpp b/platform/android/power_android.cpp
index 51283183df..0a6bf9dfcb 100644
--- a/platform/android/power_android.cpp
+++ b/platform/android/power_android.cpp
@@ -98,7 +98,7 @@ ANativeWindow *Android_JNI_GetNativeWindow(void) {
return anw;
}
-/*
+/*
* CODE CHUNK IMPORTED FROM SDL 2.0
* returns 0 on success or -1 on error (others undefined then)
* returns truthy or falsy value in plugged, charged and battery
diff --git a/platform/iphone/detect.py b/platform/iphone/detect.py
index 417571f6f3..c9f37931b0 100644
--- a/platform/iphone/detect.py
+++ b/platform/iphone/detect.py
@@ -1,7 +1,7 @@
import os
import string
import sys
-
+from methods import detect_darwin_sdk_path
def is_active():
return True
@@ -22,9 +22,8 @@ def can_build():
def get_opts():
from SCons.Variables import BoolVariable
return [
- ('IPHONEPLATFORM', 'Name of the iPhone platform', 'iPhoneOS'),
('IPHONEPATH', 'Path to iPhone toolchain', '/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain'),
- ('IPHONESDK', 'Path to the iPhone SDK', '/Applications/Xcode.app/Contents/Developer/Platforms/${IPHONEPLATFORM}.platform/Developer/SDKs/${IPHONEPLATFORM}.sdk/'),
+ ('IPHONESDK', 'Path to the iPhone SDK', ''),
BoolVariable('game_center', 'Support for game center', True),
BoolVariable('store_kit', 'Support for in-app store', True),
BoolVariable('icloud', 'Support for iCloud', True),
@@ -103,13 +102,15 @@ def configure(env):
## Compile flags
if (env["arch"] == "x86" or env["arch"] == "x86_64"):
- env['IPHONEPLATFORM'] = 'iPhoneSimulator'
+ detect_darwin_sdk_path('iphonesimulator', env)
env['ENV']['MACOSX_DEPLOYMENT_TARGET'] = '10.9'
arch_flag = "i386" if env["arch"] == "x86" else env["arch"]
env.Append(CCFLAGS=('-arch ' + arch_flag + ' -fobjc-abi-version=2 -fobjc-legacy-dispatch -fmessage-length=0 -fpascal-strings -fblocks -fasm-blocks -isysroot $IPHONESDK -mios-simulator-version-min=9.0 -DCUSTOM_MATRIX_TRANSFORM_H=\\\"build/iphone/matrix4_iphone.h\\\" -DCUSTOM_VECTOR3_TRANSFORM_H=\\\"build/iphone/vector3_iphone.h\\\"').split())
elif (env["arch"] == "arm"):
+ detect_darwin_sdk_path('iphone', env)
env.Append(CCFLAGS='-fno-objc-arc -arch armv7 -fmessage-length=0 -fno-strict-aliasing -fdiagnostics-print-source-range-info -fdiagnostics-show-category=id -fdiagnostics-parseable-fixits -fpascal-strings -fblocks -isysroot $IPHONESDK -fvisibility=hidden -mthumb "-DIBOutlet=__attribute__((iboutlet))" "-DIBOutletCollection(ClassName)=__attribute__((iboutletcollection(ClassName)))" "-DIBAction=void)__attribute__((ibaction)" -miphoneos-version-min=9.0 -MMD -MT dependencies'.split())
elif (env["arch"] == "arm64"):
+ detect_darwin_sdk_path('iphone', env)
env.Append(CCFLAGS='-fno-objc-arc -arch arm64 -fmessage-length=0 -fno-strict-aliasing -fdiagnostics-print-source-range-info -fdiagnostics-show-category=id -fdiagnostics-parseable-fixits -fpascal-strings -fblocks -fvisibility=hidden -MMD -MT dependencies -miphoneos-version-min=9.0 -isysroot $IPHONESDK'.split())
env.Append(CPPFLAGS=['-DNEED_LONG_INT'])
env.Append(CPPFLAGS=['-DLIBYUV_DISABLE_NEON'])
diff --git a/platform/iphone/export/export.cpp b/platform/iphone/export/export.cpp
index 1fc497456c..7fb3afe9a9 100644
--- a/platform/iphone/export/export.cpp
+++ b/platform/iphone/export/export.cpp
@@ -982,11 +982,27 @@ bool EditorExportPlatformIOS::can_export(const Ref<EditorExportPreset> &p_preset
err += "Custom release package not found.\n";
}
+ String team_id = p_preset->get("application/app_store_team_id");
+ if (team_id.length() == 0) {
+ err += "App Store Team ID not specified - cannot configure the project.\n";
+ }
+
+ for (unsigned int i = 0; i < (sizeof(icon_infos) / sizeof(icon_infos[0])); ++i) {
+ IconInfo info = icon_infos[i];
+ String icon_path = p_preset->get(info.preset_key);
+ if (icon_path.length() == 0) {
+ if (info.is_required) {
+ err += "Required icon is not specified in the preset.\n";
+ }
+ break;
+ }
+ }
+
if (!err.empty())
r_error = err;
r_missing_templates = !valid;
- return valid;
+ return err.empty();
}
EditorExportPlatformIOS::EditorExportPlatformIOS() {
diff --git a/platform/osx/detect.py b/platform/osx/detect.py
index c5bd64b15c..051836b66d 100644
--- a/platform/osx/detect.py
+++ b/platform/osx/detect.py
@@ -1,5 +1,6 @@
import os
import sys
+from methods import detect_darwin_sdk_path
def is_active():
@@ -23,6 +24,7 @@ def get_opts():
return [
('osxcross_sdk', 'OSXCross SDK version', 'darwin14'),
+ ('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),
]
@@ -84,6 +86,10 @@ def configure(env):
env['AS'] = mpprefix + "/libexec/llvm-" + mpclangver + "/bin/llvm-as"
env.Append(CCFLAGS=['-D__MACPORTS__']) #hack to fix libvpx MM256_BROADCASTSI128_SI256 define
+ detect_darwin_sdk_path('osx', env)
+ env.Append(CPPFLAGS=['-isysroot', '$MACOS_SDK_PATH'])
+ env.Append(LINKFLAGS=['-isysroot', '$MACOS_SDK_PATH'])
+
else: # osxcross build
root = os.environ.get("OSXCROSS_ROOT", 0)
basecmd = root + "/target/bin/x86_64-apple-" + env["osxcross_sdk"] + "-"
diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm
index 8123aaa427..e7b3e35381 100644
--- a/platform/osx/os_osx.mm
+++ b/platform/osx/os_osx.mm
@@ -76,6 +76,13 @@
#define NSWindowStyleMaskBorderless NSBorderlessWindowMask
#endif
+#ifndef NSAppKitVersionNumber10_12
+#define NSAppKitVersionNumber10_12 1504
+#endif
+#ifndef NSAppKitVersionNumber10_14
+#define NSAppKitVersionNumber10_14 1671
+#endif
+
static void get_key_modifier_state(unsigned int p_osx_state, Ref<InputEventWithModifiers> state) {
state->set_shift((p_osx_state & NSEventModifierFlagShift));
@@ -1237,7 +1244,7 @@ Error OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_a
ERR_FAIL_COND_V(window_object == nil, ERR_UNAVAILABLE);
window_view = [[GodotContentView alloc] init];
- if (@available(macOS 10.14, *)) {
+ if (NSAppKitVersionNumber >= NSAppKitVersionNumber10_14) {
[window_view setWantsLayer:TRUE];
}
@@ -1472,7 +1479,7 @@ public:
switch (p_type) {
case ERR_WARNING:
- if (floor(NSAppKitVersionNumber) >= NSAppKitVersionNumber10_12) {
+ if (NSAppKitVersionNumber >= NSAppKitVersionNumber10_12) {
os_log_info(OS_LOG_DEFAULT,
"WARNING: %{public}s: %{public}s\nAt: %{public}s:%i.",
p_function, err_details, p_file, p_line);
@@ -1482,7 +1489,7 @@ public:
logf_error("\E[0;33m At: %s:%i.\E[0m\n", p_file, p_line);
break;
case ERR_SCRIPT:
- if (floor(NSAppKitVersionNumber) >= NSAppKitVersionNumber10_12) {
+ if (NSAppKitVersionNumber >= NSAppKitVersionNumber10_12) {
os_log_error(OS_LOG_DEFAULT,
"SCRIPT ERROR: %{public}s: %{public}s\nAt: %{public}s:%i.",
p_function, err_details, p_file, p_line);
@@ -1492,7 +1499,7 @@ public:
logf_error("\E[0;35m At: %s:%i.\E[0m\n", p_file, p_line);
break;
case ERR_SHADER:
- if (floor(NSAppKitVersionNumber) >= NSAppKitVersionNumber10_12) {
+ if (NSAppKitVersionNumber >= NSAppKitVersionNumber10_12) {
os_log_error(OS_LOG_DEFAULT,
"SHADER ERROR: %{public}s: %{public}s\nAt: %{public}s:%i.",
p_function, err_details, p_file, p_line);
@@ -1503,7 +1510,7 @@ public:
break;
case ERR_ERROR:
default:
- if (floor(NSAppKitVersionNumber) >= NSAppKitVersionNumber10_12) {
+ if (NSAppKitVersionNumber >= NSAppKitVersionNumber10_12) {
os_log_error(OS_LOG_DEFAULT,
"ERROR: %{public}s: %{public}s\nAt: %{public}s:%i.",
p_function, err_details, p_file, p_line);
@@ -2174,11 +2181,7 @@ void OS_OSX::set_window_size(const Size2 p_size) {
if (menuBarHeight != 0.f) {
size.y += menuBarHeight;
} else {
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101200
if (floor(NSAppKitVersionNumber) < NSAppKitVersionNumber10_12) {
-#else
- {
-#endif
size.y += [[NSStatusBar systemStatusBar] thickness];
}
}
diff --git a/platform/windows/detect.py b/platform/windows/detect.py
index 5d5af17086..dd0042668f 100644
--- a/platform/windows/detect.py
+++ b/platform/windows/detect.py
@@ -262,7 +262,7 @@ def configure_mingw(env):
env.Append(CCFLAGS=['-O2'])
else: #optimize for size
env.Prepend(CCFLAGS=['-Os'])
-
+
env.Append(LINKFLAGS=['-Wl,--subsystem,windows'])
@@ -281,7 +281,7 @@ def configure_mingw(env):
env.Append(CCFLAGS=['-O2'])
else: #optimize for size
env.Prepend(CCFLAGS=['-Os'])
-
+
elif (env["target"] == "debug"):
env.Append(CCFLAGS=['-g3', '-DDEBUG_ENABLED', '-DDEBUG_MEMORY_ENABLED'])
diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp
index 2ab7b835b6..04854e93b6 100644
--- a/platform/x11/os_x11.cpp
+++ b/platform/x11/os_x11.cpp
@@ -369,7 +369,7 @@ Error OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_a
}
// disable resizable window
- if (!current_videomode.resizable) {
+ if (!current_videomode.resizable && !current_videomode.fullscreen) {
XSizeHints *xsh;
xsh = XAllocSizeHints();
xsh->flags = PMinSize | PMaxSize;
diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp
index 929b4624ee..3dde228bfa 100644
--- a/scene/2d/physics_body_2d.cpp
+++ b/scene/2d/physics_body_2d.cpp
@@ -1425,6 +1425,10 @@ void KinematicBody2D::set_sync_to_physics(bool p_enable) {
return;
}
sync_to_physics = p_enable;
+
+ if (Engine::get_singleton()->is_editor_hint())
+ return;
+
if (p_enable) {
Physics2DServer::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed");
set_only_update_transform_changes(true);
diff --git a/scene/2d/visibility_notifier_2d.cpp b/scene/2d/visibility_notifier_2d.cpp
index 7d7c47619a..d656ba0f64 100644
--- a/scene/2d/visibility_notifier_2d.cpp
+++ b/scene/2d/visibility_notifier_2d.cpp
@@ -190,7 +190,7 @@ void VisibilityEnabler2D::_find_nodes(Node *p_node) {
if (enabler[ENABLER_FREEZE_BODIES]) {
RigidBody2D *rb2d = Object::cast_to<RigidBody2D>(p_node);
- if (rb2d && ((rb2d->get_mode() == RigidBody2D::MODE_CHARACTER || (rb2d->get_mode() == RigidBody2D::MODE_RIGID && !rb2d->is_able_to_sleep())))) {
+ if (rb2d && ((rb2d->get_mode() == RigidBody2D::MODE_CHARACTER || rb2d->get_mode() == RigidBody2D::MODE_RIGID))) {
add = true;
meta = rb2d->get_mode();
diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp
index 9148b436a0..bcfcf33e57 100644
--- a/scene/3d/physics_body.cpp
+++ b/scene/3d/physics_body.cpp
@@ -1907,6 +1907,26 @@ bool PhysicalBone::SixDOFJointData::_set(const StringName &p_name, const Variant
if (j.is_valid())
PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_LINEAR_LIMIT_SOFTNESS, axis_data[axis].linear_limit_softness);
+ } else if ("linear_spring_enabled" == var_name) {
+ axis_data[axis].linear_spring_enabled = p_value;
+ if (j.is_valid())
+ PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(j, axis, PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING, axis_data[axis].linear_spring_enabled);
+
+ } else if ("linear_spring_stiffness" == var_name) {
+ axis_data[axis].linear_spring_stiffness = p_value;
+ if (j.is_valid())
+ PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS, axis_data[axis].linear_spring_stiffness);
+
+ } else if ("linear_spring_damping" == var_name) {
+ axis_data[axis].linear_spring_damping = p_value;
+ if (j.is_valid())
+ PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_DAMPING, axis_data[axis].linear_spring_damping);
+
+ } else if ("linear_equilibrium_point" == var_name) {
+ axis_data[axis].linear_equilibrium_point = p_value;
+ if (j.is_valid())
+ PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT, axis_data[axis].linear_equilibrium_point);
+
} else if ("linear_restitution" == var_name) {
axis_data[axis].linear_restitution = p_value;
if (j.is_valid())
@@ -1952,6 +1972,26 @@ bool PhysicalBone::SixDOFJointData::_set(const StringName &p_name, const Variant
if (j.is_valid())
PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_ANGULAR_ERP, axis_data[axis].erp);
+ } else if ("angular_spring_enabled" == var_name) {
+ axis_data[axis].angular_spring_enabled = p_value;
+ if (j.is_valid())
+ PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(j, axis, PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING, axis_data[axis].angular_spring_enabled);
+
+ } else if ("angular_spring_stiffness" == var_name) {
+ axis_data[axis].angular_spring_stiffness = p_value;
+ if (j.is_valid())
+ PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS, axis_data[axis].angular_spring_stiffness);
+
+ } else if ("angular_spring_damping" == var_name) {
+ axis_data[axis].angular_spring_damping = p_value;
+ if (j.is_valid())
+ PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_DAMPING, axis_data[axis].angular_spring_damping);
+
+ } else if ("angular_equilibrium_point" == var_name) {
+ axis_data[axis].angular_equilibrium_point = p_value;
+ if (j.is_valid())
+ PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT, axis_data[axis].angular_equilibrium_point);
+
} else {
return false;
}
@@ -1990,6 +2030,14 @@ bool PhysicalBone::SixDOFJointData::_get(const StringName &p_name, Variant &r_re
r_ret = axis_data[axis].linear_limit_lower;
} else if ("linear_limit_softness" == var_name) {
r_ret = axis_data[axis].linear_limit_softness;
+ } else if ("linear_spring_enabled" == var_name) {
+ r_ret = axis_data[axis].linear_spring_enabled;
+ } else if ("linear_spring_stiffness" == var_name) {
+ r_ret = axis_data[axis].linear_spring_stiffness;
+ } else if ("linear_spring_damping" == var_name) {
+ r_ret = axis_data[axis].linear_spring_damping;
+ } else if ("linear_equilibrium_point" == var_name) {
+ r_ret = axis_data[axis].linear_equilibrium_point;
} else if ("linear_restitution" == var_name) {
r_ret = axis_data[axis].linear_restitution;
} else if ("linear_damping" == var_name) {
@@ -2008,6 +2056,14 @@ bool PhysicalBone::SixDOFJointData::_get(const StringName &p_name, Variant &r_re
r_ret = axis_data[axis].angular_damping;
} else if ("erp" == var_name) {
r_ret = axis_data[axis].erp;
+ } else if ("angular_spring_enabled" == var_name) {
+ r_ret = axis_data[axis].angular_spring_enabled;
+ } else if ("angular_spring_stiffness" == var_name) {
+ r_ret = axis_data[axis].angular_spring_stiffness;
+ } else if ("angular_spring_damping" == var_name) {
+ r_ret = axis_data[axis].angular_spring_damping;
+ } else if ("angular_equilibrium_point" == var_name) {
+ r_ret = axis_data[axis].angular_equilibrium_point;
} else {
return false;
}
@@ -2022,6 +2078,10 @@ void PhysicalBone::SixDOFJointData::_get_property_list(List<PropertyInfo> *p_lis
p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/linear_limit_upper"));
p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/linear_limit_lower"));
p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/linear_limit_softness", PROPERTY_HINT_RANGE, "0.01,16,0.01"));
+ p_list->push_back(PropertyInfo(Variant::BOOL, "joint_constraints/" + axis_names[i] + "/linear_spring_enabled"));
+ p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/linear_spring_stiffness"));
+ p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/linear_spring_damping"));
+ p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/linear_equilibrium_point"));
p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/linear_restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01"));
p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/linear_damping", PROPERTY_HINT_RANGE, "0.01,16,0.01"));
p_list->push_back(PropertyInfo(Variant::BOOL, "joint_constraints/" + axis_names[i] + "/angular_limit_enabled"));
@@ -2031,6 +2091,10 @@ void PhysicalBone::SixDOFJointData::_get_property_list(List<PropertyInfo> *p_lis
p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/angular_restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01"));
p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/angular_damping", PROPERTY_HINT_RANGE, "0.01,16,0.01"));
p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/erp"));
+ p_list->push_back(PropertyInfo(Variant::BOOL, "joint_constraints/" + axis_names[i] + "/angular_spring_enabled"));
+ p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/angular_spring_stiffness"));
+ p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/angular_spring_damping"));
+ p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/angular_equilibrium_point"));
}
}
@@ -2294,6 +2358,10 @@ void PhysicalBone::_reload_joint() {
PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer::G6DOF_JOINT_LINEAR_UPPER_LIMIT, g6dofjd->axis_data[axis].linear_limit_upper);
PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer::G6DOF_JOINT_LINEAR_LOWER_LIMIT, g6dofjd->axis_data[axis].linear_limit_lower);
PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer::G6DOF_JOINT_LINEAR_LIMIT_SOFTNESS, g6dofjd->axis_data[axis].linear_limit_softness);
+ PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(joint, static_cast<Vector3::Axis>(axis), PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING, g6dofjd->axis_data[axis].linear_spring_enabled);
+ PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS, g6dofjd->axis_data[axis].linear_spring_stiffness);
+ PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_DAMPING, g6dofjd->axis_data[axis].linear_spring_damping);
+ PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT, g6dofjd->axis_data[axis].linear_equilibrium_point);
PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer::G6DOF_JOINT_LINEAR_RESTITUTION, g6dofjd->axis_data[axis].linear_restitution);
PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer::G6DOF_JOINT_LINEAR_DAMPING, g6dofjd->axis_data[axis].linear_damping);
PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(joint, static_cast<Vector3::Axis>(axis), PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT, g6dofjd->axis_data[axis].angular_limit_enabled);
@@ -2303,6 +2371,10 @@ void PhysicalBone::_reload_joint() {
PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer::G6DOF_JOINT_ANGULAR_RESTITUTION, g6dofjd->axis_data[axis].angular_restitution);
PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer::G6DOF_JOINT_ANGULAR_DAMPING, g6dofjd->axis_data[axis].angular_damping);
PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer::G6DOF_JOINT_ANGULAR_ERP, g6dofjd->axis_data[axis].erp);
+ PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(joint, static_cast<Vector3::Axis>(axis), PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING, g6dofjd->axis_data[axis].angular_spring_enabled);
+ PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS, g6dofjd->axis_data[axis].angular_spring_stiffness);
+ PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_DAMPING, g6dofjd->axis_data[axis].angular_spring_damping);
+ PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT, g6dofjd->axis_data[axis].angular_equilibrium_point);
}
} break;
diff --git a/scene/3d/physics_body.h b/scene/3d/physics_body.h
index 20d948b6eb..5474290c07 100644
--- a/scene/3d/physics_body.h
+++ b/scene/3d/physics_body.h
@@ -494,6 +494,10 @@ public:
real_t linear_limit_softness;
real_t linear_restitution;
real_t linear_damping;
+ bool linear_spring_enabled;
+ real_t linear_spring_stiffness;
+ real_t linear_spring_damping;
+ real_t linear_equilibrium_point;
bool angular_limit_enabled;
real_t angular_limit_upper;
real_t angular_limit_lower;
@@ -501,6 +505,10 @@ public:
real_t angular_restitution;
real_t angular_damping;
real_t erp;
+ bool angular_spring_enabled;
+ real_t angular_spring_stiffness;
+ real_t angular_spring_damping;
+ real_t angular_equilibrium_point;
SixDOFAxisData() :
linear_limit_enabled(true),
@@ -509,13 +517,21 @@ public:
linear_limit_softness(0.7),
linear_restitution(0.5),
linear_damping(1.),
+ linear_spring_enabled(false),
+ linear_spring_stiffness(0),
+ linear_spring_damping(0),
+ linear_equilibrium_point(0),
angular_limit_enabled(true),
angular_limit_upper(0),
angular_limit_lower(0),
angular_limit_softness(0.5),
angular_restitution(0),
angular_damping(1.),
- erp(0.5) {}
+ erp(0.5),
+ angular_spring_enabled(false),
+ angular_spring_stiffness(0),
+ angular_spring_damping(0.),
+ angular_equilibrium_point(0) {}
};
virtual JointType get_joint_type() { return JOINT_TYPE_6DOF; }
diff --git a/scene/3d/physics_joint.cpp b/scene/3d/physics_joint.cpp
index 1adf1c5d79..02c6b1d969 100644
--- a/scene/3d/physics_joint.cpp
+++ b/scene/3d/physics_joint.cpp
@@ -776,7 +776,6 @@ void Generic6DOFJoint::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_motor_z/target_velocity"), "set_param_z", "get_param_z", PARAM_LINEAR_MOTOR_TARGET_VELOCITY);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_motor_z/force_limit"), "set_param_z", "get_param_z", PARAM_LINEAR_MOTOR_FORCE_LIMIT);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_spring_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_LINEAR_SPRING);
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_spring_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_LINEAR_SPRING);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_spring_z/stiffness"), "set_param_z", "get_param_z", PARAM_LINEAR_SPRING_STIFFNESS);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_spring_z/damping"), "set_param_z", "get_param_z", PARAM_LINEAR_SPRING_DAMPING);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_spring_z/equilibrium_point"), "set_param_z", "get_param_z", PARAM_LINEAR_SPRING_EQUILIBRIUM_POINT);
diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp
index 8e00fbe735..5bde224ce3 100644
--- a/scene/3d/sprite_3d.cpp
+++ b/scene/3d/sprite_3d.cpp
@@ -461,6 +461,13 @@ void Sprite3D::_draw() {
int axis = get_axis();
normal[axis] = 1.0;
+ Plane tangent;
+ if (axis == Vector3::AXIS_X) {
+ tangent = Plane(0, 0, -1, -1);
+ } else {
+ tangent = Plane(1, 0, 0, -1);
+ }
+
RID mat = SpatialMaterial::get_material_rid_for_2d(get_draw_flag(FLAG_SHADED), get_draw_flag(FLAG_TRANSPARENT), get_draw_flag(FLAG_DOUBLE_SIDED), get_alpha_cut_mode() == ALPHA_CUT_DISCARD, get_alpha_cut_mode() == ALPHA_CUT_OPAQUE_PREPASS);
VS::get_singleton()->immediate_set_material(immediate, mat);
@@ -487,6 +494,7 @@ void Sprite3D::_draw() {
for (int i = 0; i < 4; i++) {
VS::get_singleton()->immediate_normal(immediate, normal);
+ VS::get_singleton()->immediate_tangent(immediate, tangent);
VS::get_singleton()->immediate_color(immediate, color);
VS::get_singleton()->immediate_uv(immediate, uvs[i]);
@@ -761,6 +769,13 @@ void AnimatedSprite3D::_draw() {
int axis = get_axis();
normal[axis] = 1.0;
+ Plane tangent;
+ if (axis == Vector3::AXIS_X) {
+ tangent = Plane(0, 0, -1, -1);
+ } else {
+ tangent = Plane(1, 0, 0, -1);
+ }
+
RID mat = SpatialMaterial::get_material_rid_for_2d(get_draw_flag(FLAG_SHADED), get_draw_flag(FLAG_TRANSPARENT), get_draw_flag(FLAG_DOUBLE_SIDED), get_alpha_cut_mode() == ALPHA_CUT_DISCARD, get_alpha_cut_mode() == ALPHA_CUT_OPAQUE_PREPASS);
VS::get_singleton()->immediate_set_material(immediate, mat);
@@ -788,6 +803,7 @@ void AnimatedSprite3D::_draw() {
for (int i = 0; i < 4; i++) {
VS::get_singleton()->immediate_normal(immediate, normal);
+ VS::get_singleton()->immediate_tangent(immediate, tangent);
VS::get_singleton()->immediate_color(immediate, color);
VS::get_singleton()->immediate_uv(immediate, uvs[i]);
diff --git a/scene/3d/visibility_notifier.cpp b/scene/3d/visibility_notifier.cpp
index c69387d082..9a0832b27a 100644
--- a/scene/3d/visibility_notifier.cpp
+++ b/scene/3d/visibility_notifier.cpp
@@ -153,7 +153,7 @@ void VisibilityEnabler::_find_nodes(Node *p_node) {
if (enabler[ENABLER_FREEZE_BODIES]) {
RigidBody *rb = Object::cast_to<RigidBody>(p_node);
- if (rb && ((rb->get_mode() == RigidBody::MODE_CHARACTER || (rb->get_mode() == RigidBody::MODE_RIGID && !rb->is_able_to_sleep())))) {
+ if (rb && ((rb->get_mode() == RigidBody::MODE_CHARACTER || rb->get_mode() == RigidBody::MODE_RIGID))) {
add = true;
meta = rb->get_mode();
diff --git a/scene/animation/animation_blend_space_2d.cpp b/scene/animation/animation_blend_space_2d.cpp
index 9321133d5f..866b85c4c7 100644
--- a/scene/animation/animation_blend_space_2d.cpp
+++ b/scene/animation/animation_blend_space_2d.cpp
@@ -33,9 +33,17 @@
void AnimationNodeBlendSpace2D::get_parameter_list(List<PropertyInfo> *r_list) const {
r_list->push_back(PropertyInfo(Variant::VECTOR2, blend_position));
+ r_list->push_back(PropertyInfo(Variant::INT, closest, PROPERTY_HINT_NONE, "", 0));
+ r_list->push_back(PropertyInfo(Variant::REAL, length_internal, PROPERTY_HINT_NONE, "", 0));
}
Variant AnimationNodeBlendSpace2D::get_parameter_default_value(const StringName &p_parameter) const {
- return Vector2();
+ if (p_parameter == closest) {
+ return -1;
+ } else if (p_parameter == length_internal) {
+ return 0;
+ } else {
+ return Vector2();
+ }
}
void AnimationNodeBlendSpace2D::get_child_nodes(List<ChildNode> *r_child_nodes) {
@@ -412,84 +420,124 @@ float AnimationNodeBlendSpace2D::process(float p_time, bool p_seek) {
_update_triangles();
Vector2 blend_pos = get_parameter(blend_position);
+ int closest = get_parameter(this->closest);
+ float length_internal = get_parameter(this->length_internal);
+ float mind = 0; //time of min distance point
- if (triangles.size() == 0)
- return 0;
+ if (blend_mode == BLEND_MODE_INTERPOLATED) {
- Vector2 best_point;
- bool first = true;
- int blend_triangle = -1;
- float blend_weights[3] = { 0, 0, 0 };
+ if (triangles.size() == 0)
+ return 0;
- for (int i = 0; i < triangles.size(); i++) {
- Vector2 points[3];
- for (int j = 0; j < 3; j++) {
- points[j] = get_blend_point_position(get_triangle_point(i, j));
- }
+ Vector2 best_point;
+ bool first = true;
+ int blend_triangle = -1;
+ float blend_weights[3] = { 0, 0, 0 };
- if (Geometry::is_point_in_triangle(blend_pos, points[0], points[1], points[2])) {
+ for (int i = 0; i < triangles.size(); i++) {
+ Vector2 points[3];
+ for (int j = 0; j < 3; j++) {
+ points[j] = get_blend_point_position(get_triangle_point(i, j));
+ }
- blend_triangle = i;
- _blend_triangle(blend_pos, points, blend_weights);
- break;
- }
+ if (Geometry::is_point_in_triangle(blend_pos, points[0], points[1], points[2])) {
- for (int j = 0; j < 3; j++) {
- Vector2 s[2] = {
- points[j],
- points[(j + 1) % 3]
- };
- Vector2 closest = Geometry::get_closest_point_to_segment_2d(blend_pos, s);
- if (first || closest.distance_to(blend_pos) < best_point.distance_to(blend_pos)) {
- best_point = closest;
blend_triangle = i;
- first = false;
- float d = s[0].distance_to(s[1]);
- if (d == 0.0) {
- blend_weights[j] = 1.0;
- blend_weights[(j + 1) % 3] = 0.0;
- blend_weights[(j + 2) % 3] = 0.0;
- } else {
- float c = s[0].distance_to(closest) / d;
-
- blend_weights[j] = 1.0 - c;
- blend_weights[(j + 1) % 3] = c;
- blend_weights[(j + 2) % 3] = 0.0;
+ _blend_triangle(blend_pos, points, blend_weights);
+ break;
+ }
+
+ for (int j = 0; j < 3; j++) {
+ Vector2 s[2] = {
+ points[j],
+ points[(j + 1) % 3]
+ };
+ Vector2 closest = Geometry::get_closest_point_to_segment_2d(blend_pos, s);
+ if (first || closest.distance_to(blend_pos) < best_point.distance_to(blend_pos)) {
+ best_point = closest;
+ blend_triangle = i;
+ first = false;
+ float d = s[0].distance_to(s[1]);
+ if (d == 0.0) {
+ blend_weights[j] = 1.0;
+ blend_weights[(j + 1) % 3] = 0.0;
+ blend_weights[(j + 2) % 3] = 0.0;
+ } else {
+ float c = s[0].distance_to(closest) / d;
+
+ blend_weights[j] = 1.0 - c;
+ blend_weights[(j + 1) % 3] = c;
+ blend_weights[(j + 2) % 3] = 0.0;
+ }
}
}
}
- }
- ERR_FAIL_COND_V(blend_triangle == -1, 0); //should never reach here
+ ERR_FAIL_COND_V(blend_triangle == -1, 0); //should never reach here
- int triangle_points[3];
- for (int j = 0; j < 3; j++) {
- triangle_points[j] = get_triangle_point(blend_triangle, j);
- }
+ int triangle_points[3];
+ for (int j = 0; j < 3; j++) {
+ triangle_points[j] = get_triangle_point(blend_triangle, j);
+ }
- first = true;
- float mind = 0;
- for (int i = 0; i < blend_points_used; i++) {
+ first = true;
- bool found = false;
- for (int j = 0; j < 3; j++) {
- if (i == triangle_points[j]) {
- //blend with the given weight
- float t = blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, blend_weights[j], FILTER_IGNORE, false);
- if (first || t < mind) {
- mind = t;
- first = false;
+ for (int i = 0; i < blend_points_used; i++) {
+
+ bool found = false;
+ for (int j = 0; j < 3; j++) {
+ if (i == triangle_points[j]) {
+ //blend with the given weight
+ float t = blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, blend_weights[j], FILTER_IGNORE, false);
+ if (first || t < mind) {
+ mind = t;
+ first = false;
+ }
+ found = true;
+ break;
}
- found = true;
- break;
+ }
+
+ if (!found) {
+ //ignore
+ blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, 0, FILTER_IGNORE, false);
+ }
+ }
+ } else {
+
+ int new_closest = -1;
+ float new_closest_dist = 1e20;
+
+ for (int i = 0; i < blend_points_used; i++) {
+
+ float d = blend_points[i].position.distance_squared_to(blend_pos);
+ if (d < new_closest_dist) {
+
+ new_closest = i;
+ new_closest_dist = d;
}
}
- if (!found) {
- //ignore
- blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, 0, FILTER_IGNORE, false);
+ if (new_closest != closest) {
+
+ float from = 0;
+ if (blend_mode == BLEND_MODE_DISCRETE_CARRY && closest != -1) {
+ //see how much animation remains
+ from = blend_node(blend_points[closest].name, blend_points[closest].node, p_time, true, 0.0, FILTER_IGNORE, false) - length_internal;
+ }
+
+ mind = blend_node(blend_points[new_closest].name, blend_points[new_closest].node, from, true, 1.0, FILTER_IGNORE, false) + from;
+ length_internal = from + mind;
+
+ closest = new_closest;
+
+ } else {
+ mind = blend_node(blend_points[closest].name, blend_points[closest].node, p_time, p_seek, 1.0, FILTER_IGNORE, false);
}
}
+
+ set_parameter(this->closest, closest);
+ set_parameter(this->length_internal, length_internal);
return mind;
}
@@ -527,6 +575,14 @@ void AnimationNodeBlendSpace2D::_tree_changed() {
emit_signal("tree_changed");
}
+void AnimationNodeBlendSpace2D::set_blend_mode(BlendMode p_blend_mode) {
+ blend_mode = p_blend_mode;
+}
+
+AnimationNodeBlendSpace2D::BlendMode AnimationNodeBlendSpace2D::get_blend_mode() const {
+ return blend_mode;
+}
+
void AnimationNodeBlendSpace2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_blend_point", "node", "pos", "at_index"), &AnimationNodeBlendSpace2D::add_blend_point, DEFVAL(-1));
@@ -565,6 +621,9 @@ void AnimationNodeBlendSpace2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_auto_triangles", "enable"), &AnimationNodeBlendSpace2D::set_auto_triangles);
ClassDB::bind_method(D_METHOD("get_auto_triangles"), &AnimationNodeBlendSpace2D::get_auto_triangles);
+ ClassDB::bind_method(D_METHOD("set_blend_mode", "mode"), &AnimationNodeBlendSpace2D::set_blend_mode);
+ ClassDB::bind_method(D_METHOD("get_blend_mode"), &AnimationNodeBlendSpace2D::get_blend_mode);
+
ClassDB::bind_method(D_METHOD("_tree_changed"), &AnimationNodeBlendSpace2D::_tree_changed);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_triangles", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_auto_triangles", "get_auto_triangles");
@@ -581,6 +640,11 @@ void AnimationNodeBlendSpace2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "snap", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_snap", "get_snap");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "x_label", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_x_label", "get_x_label");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "y_label", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_y_label", "get_y_label");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "blend_mode", PROPERTY_HINT_ENUM, "Interpolated,Discrete,Carry", PROPERTY_USAGE_NOEDITOR), "set_blend_mode", "get_blend_mode");
+
+ BIND_ENUM_CONSTANT(BLEND_MODE_INTERPOLATED);
+ BIND_ENUM_CONSTANT(BLEND_MODE_DISCRETE);
+ BIND_ENUM_CONSTANT(BLEND_MODE_DISCRETE_CARRY);
}
AnimationNodeBlendSpace2D::AnimationNodeBlendSpace2D() {
@@ -597,6 +661,9 @@ AnimationNodeBlendSpace2D::AnimationNodeBlendSpace2D() {
y_label = "y";
trianges_dirty = false;
blend_position = "blend_position";
+ closest = "closest";
+ length_internal = "length_internal";
+ blend_mode = BLEND_MODE_INTERPOLATED;
}
AnimationNodeBlendSpace2D::~AnimationNodeBlendSpace2D() {
diff --git a/scene/animation/animation_blend_space_2d.h b/scene/animation/animation_blend_space_2d.h
index 2c684687de..60671f1816 100644
--- a/scene/animation/animation_blend_space_2d.h
+++ b/scene/animation/animation_blend_space_2d.h
@@ -35,7 +35,14 @@
class AnimationNodeBlendSpace2D : public AnimationRootNode {
GDCLASS(AnimationNodeBlendSpace2D, AnimationRootNode)
+public:
+ enum BlendMode {
+ BLEND_MODE_INTERPOLATED,
+ BLEND_MODE_DISCRETE,
+ BLEND_MODE_DISCRETE_CARRY,
+ };
+protected:
enum {
MAX_BLEND_POINTS = 64
};
@@ -56,11 +63,14 @@ class AnimationNodeBlendSpace2D : public AnimationRootNode {
Vector<BlendTriangle> triangles;
StringName blend_position;
+ StringName closest;
+ StringName length_internal;
Vector2 max_space;
Vector2 min_space;
Vector2 snap;
String x_label;
String y_label;
+ BlendMode blend_mode;
void _add_blend_point(int p_index, const Ref<AnimationRootNode> &p_node);
void _set_triangles(const Vector<int> &p_triangles);
@@ -122,10 +132,15 @@ public:
void set_auto_triangles(bool p_enable);
bool get_auto_triangles() const;
+ void set_blend_mode(BlendMode p_blend_mode);
+ BlendMode get_blend_mode() const;
+
virtual Ref<AnimationNode> get_child_by_name(const StringName &p_name);
AnimationNodeBlendSpace2D();
~AnimationNodeBlendSpace2D();
};
+VARIANT_ENUM_CAST(AnimationNodeBlendSpace2D::BlendMode)
+
#endif // ANIMATION_BLEND_SPACE_2D_H
diff --git a/scene/animation/animation_blend_tree.cpp b/scene/animation/animation_blend_tree.cpp
index a08639089e..5b413737a9 100644
--- a/scene/animation/animation_blend_tree.cpp
+++ b/scene/animation/animation_blend_tree.cpp
@@ -700,7 +700,7 @@ String AnimationNodeTransition::get_input_caption(int p_input) const {
if (tree.is_valid() && current >= 0) {
prev = current;
- prev_xfading = xfade;
+ prev_xfading = xfade;
time = 0;
current = p_current;
switched = true;
diff --git a/scene/animation/skeleton_ik.cpp b/scene/animation/skeleton_ik.cpp
index 83f45afac8..3119e29586 100644
--- a/scene/animation/skeleton_ik.cpp
+++ b/scene/animation/skeleton_ik.cpp
@@ -280,7 +280,7 @@ void FabrikInverseKinematic::make_goal(Task *p_task, const Transform &p_inverse_
}
}
-void FabrikInverseKinematic::solve(Task *p_task, real_t blending_delta, bool p_use_magnet, const Vector3 &p_magnet_position) {
+void FabrikInverseKinematic::solve(Task *p_task, real_t blending_delta, bool override_tip_basis, bool p_use_magnet, const Vector3 &p_magnet_position) {
if (blending_delta <= 0.01f) {
return; // Skip solving
@@ -314,7 +314,10 @@ void FabrikInverseKinematic::solve(Task *p_task, real_t blending_delta, bool p_u
}
} else {
// Set target orientation to tip
- new_bone_pose.basis = p_task->chain.tips[0].end_effector->goal_transform.basis;
+ if (override_tip_basis)
+ new_bone_pose.basis = p_task->chain.tips[0].end_effector->goal_transform.basis;
+ else
+ new_bone_pose.basis = new_bone_pose.basis * p_task->chain.tips[0].end_effector->goal_transform.basis;
}
p_task->skeleton->set_bone_global_pose(ci->bone, new_bone_pose);
@@ -366,6 +369,9 @@ void SkeletonIK::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_target_node", "node"), &SkeletonIK::set_target_node);
ClassDB::bind_method(D_METHOD("get_target_node"), &SkeletonIK::get_target_node);
+ ClassDB::bind_method(D_METHOD("set_override_tip_basis", "override"), &SkeletonIK::set_override_tip_basis);
+ ClassDB::bind_method(D_METHOD("is_override_tip_basis"), &SkeletonIK::is_override_tip_basis);
+
ClassDB::bind_method(D_METHOD("set_use_magnet", "use"), &SkeletonIK::set_use_magnet);
ClassDB::bind_method(D_METHOD("is_using_magnet"), &SkeletonIK::is_using_magnet);
@@ -388,6 +394,7 @@ void SkeletonIK::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::STRING, "tip_bone"), "set_tip_bone", "get_tip_bone");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "interpolation", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_interpolation", "get_interpolation");
ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "target"), "set_target_transform", "get_target_transform");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "override_tip_basis"), "set_override_tip_basis", "is_override_tip_basis");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_magnet"), "set_use_magnet", "is_using_magnet");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "magnet"), "set_magnet_position", "get_magnet_position");
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "target_node"), "set_target_node", "get_target_node");
@@ -418,6 +425,7 @@ void SkeletonIK::_notification(int p_what) {
SkeletonIK::SkeletonIK() :
Node(),
interpolation(1),
+ override_tip_basis(true),
use_magnet(false),
min_distance(0.01),
max_iterations(10),
@@ -478,6 +486,14 @@ NodePath SkeletonIK::get_target_node() {
return target_node_path_override;
}
+void SkeletonIK::set_override_tip_basis(bool p_override) {
+ override_tip_basis = p_override;
+}
+
+bool SkeletonIK::is_override_tip_basis() const {
+ return override_tip_basis;
+}
+
void SkeletonIK::set_use_magnet(bool p_use) {
use_magnet = p_use;
}
@@ -555,7 +571,7 @@ void SkeletonIK::reload_goal() {
void SkeletonIK::_solve_chain() {
if (!task)
return;
- FabrikInverseKinematic::solve(task, interpolation, use_magnet, magnet_position);
+ FabrikInverseKinematic::solve(task, interpolation, override_tip_basis, use_magnet, magnet_position);
}
#endif // _3D_DISABLED
diff --git a/scene/animation/skeleton_ik.h b/scene/animation/skeleton_ik.h
index 202d6959bb..b9628c479c 100644
--- a/scene/animation/skeleton_ik.h
+++ b/scene/animation/skeleton_ik.h
@@ -138,7 +138,7 @@ public:
// The goal of chain should be always in local space
static void set_goal(Task *p_task, const Transform &p_goal);
static void make_goal(Task *p_task, const Transform &p_inverse_transf, real_t blending_delta);
- static void solve(Task *p_task, real_t blending_delta, bool p_use_magnet, const Vector3 &p_magnet_position);
+ static void solve(Task *p_task, real_t blending_delta, bool override_tip_basis, bool p_use_magnet, const Vector3 &p_magnet_position);
};
class SkeletonIK : public Node {
@@ -149,6 +149,7 @@ class SkeletonIK : public Node {
real_t interpolation;
Transform target;
NodePath target_node_path_override;
+ bool override_tip_basis;
bool use_magnet;
Vector3 magnet_position;
@@ -185,6 +186,9 @@ public:
void set_target_node(const NodePath &p_node);
NodePath get_target_node();
+ void set_override_tip_basis(bool p_override);
+ bool is_override_tip_basis() const;
+
void set_use_magnet(bool p_use);
bool is_using_magnet() const;
diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp
index d37eb22c4d..1ac19774f7 100644
--- a/scene/gui/base_button.cpp
+++ b/scene/gui/base_button.cpp
@@ -406,6 +406,16 @@ bool BaseButton::is_toggle_mode() const {
return toggle_mode;
}
+void BaseButton::set_shortcut_in_tooltip(bool p_on) {
+
+ shortcut_in_tooltip = p_on;
+}
+
+bool BaseButton::is_shortcut_in_tooltip_enabled() const {
+
+ return shortcut_in_tooltip;
+}
+
void BaseButton::set_action_mode(ActionMode p_mode) {
action_mode = p_mode;
@@ -471,7 +481,7 @@ void BaseButton::_unhandled_input(Ref<InputEvent> p_event) {
String BaseButton::get_tooltip(const Point2 &p_pos) const {
String tooltip = Control::get_tooltip(p_pos);
- if (shortcut.is_valid() && shortcut->is_valid()) {
+ if (shortcut_in_tooltip && shortcut.is_valid() && shortcut->is_valid()) {
String text = shortcut->get_name() + " (" + shortcut->get_as_text() + ")";
if (shortcut->get_name().nocasecmp_to(tooltip) != 0) {
text += "\n" + tooltip;
@@ -510,6 +520,8 @@ void BaseButton::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_hovered"), &BaseButton::is_hovered);
ClassDB::bind_method(D_METHOD("set_toggle_mode", "enabled"), &BaseButton::set_toggle_mode);
ClassDB::bind_method(D_METHOD("is_toggle_mode"), &BaseButton::is_toggle_mode);
+ ClassDB::bind_method(D_METHOD("set_shortcut_in_tooltip", "enabled"), &BaseButton::set_shortcut_in_tooltip);
+ ClassDB::bind_method(D_METHOD("is_shortcut_in_tooltip_enabled"), &BaseButton::is_shortcut_in_tooltip_enabled);
ClassDB::bind_method(D_METHOD("set_disabled", "disabled"), &BaseButton::set_disabled);
ClassDB::bind_method(D_METHOD("is_disabled"), &BaseButton::is_disabled);
ClassDB::bind_method(D_METHOD("set_action_mode", "mode"), &BaseButton::set_action_mode);
@@ -535,6 +547,7 @@ void BaseButton::_bind_methods() {
ADD_SIGNAL(MethodInfo("toggled", PropertyInfo(Variant::BOOL, "button_pressed")));
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disabled"), "set_disabled", "is_disabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "toggle_mode"), "set_toggle_mode", "is_toggle_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shortcut_in_tooltip"), "set_shortcut_in_tooltip", "is_shortcut_in_tooltip_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "pressed"), "set_pressed", "is_pressed");
ADD_PROPERTY(PropertyInfo(Variant::INT, "action_mode", PROPERTY_HINT_ENUM, "Button Press,Button Release"), "set_action_mode", "get_action_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "button_mask", PROPERTY_HINT_FLAGS, "Mouse Left, Mouse Right, Mouse Middle"), "set_button_mask", "get_button_mask");
@@ -555,6 +568,7 @@ void BaseButton::_bind_methods() {
BaseButton::BaseButton() {
toggle_mode = false;
+ shortcut_in_tooltip = true;
status.pressed = false;
status.press_attempt = false;
status.hovering = false;
diff --git a/scene/gui/base_button.h b/scene/gui/base_button.h
index 176d9fc213..a131e719ad 100644
--- a/scene/gui/base_button.h
+++ b/scene/gui/base_button.h
@@ -51,6 +51,7 @@ public:
private:
int button_mask;
bool toggle_mode;
+ bool shortcut_in_tooltip;
FocusMode enabled_focus_mode;
Ref<ShortCut> shortcut;
@@ -100,6 +101,9 @@ public:
void set_toggle_mode(bool p_on);
bool is_toggle_mode() const;
+ void set_shortcut_in_tooltip(bool p_on);
+ bool is_shortcut_in_tooltip_enabled() const;
+
void set_disabled(bool p_disabled);
bool is_disabled() const;
diff --git a/scene/gui/split_container.cpp b/scene/gui/split_container.cpp
index c38c411333..3554f04cc0 100644
--- a/scene/gui/split_container.cpp
+++ b/scene/gui/split_container.cpp
@@ -62,39 +62,28 @@ void SplitContainer::_resort() {
// If we have only one element
if (!first || !second) {
if (first) {
- fit_child_in_rect(_getch(0), Rect2(Point2(), get_size()));
+ fit_child_in_rect(first, Rect2(Point2(), get_size()));
} else if (second) {
- fit_child_in_rect(_getch(1), Rect2(Point2(), get_size()));
+ fit_child_in_rect(second, Rect2(Point2(), get_size()));
}
return;
}
// Determine expanded children
- bool first_expanded = false;
- bool second_expanded = false;
- if (vertical) {
- first_expanded = first->get_v_size_flags() & SIZE_EXPAND;
- second_expanded = second->get_v_size_flags() & SIZE_EXPAND;
- } else {
- first_expanded = first->get_h_size_flags() & SIZE_EXPAND;
- second_expanded = second->get_h_size_flags() & SIZE_EXPAND;
- }
+ bool first_expanded = (vertical ? first->get_v_size_flags() : first->get_h_size_flags()) & SIZE_EXPAND;
+ bool second_expanded = (vertical ? second->get_v_size_flags() : second->get_h_size_flags()) & SIZE_EXPAND;
// Determine the separation between items
Ref<Texture> g = get_icon("grabber");
int sep = get_constant("separation");
- if (dragger_visibility == DRAGGER_HIDDEN_COLLAPSED) {
- sep = 0;
- } else {
- sep = MAX(sep, vertical ? g->get_height() : g->get_width());
- }
+ sep = (dragger_visibility != DRAGGER_HIDDEN_COLLAPSED) ? MAX(sep, vertical ? g->get_height() : g->get_width()) : 0;
// Compute the minimum size
Size2 ms_first = first->get_combined_minimum_size();
Size2 ms_second = second->get_combined_minimum_size();
+ // Compute the separator position without the split offset
float ratio = first->get_stretch_ratio() / (first->get_stretch_ratio() + second->get_stretch_ratio());
-
int no_offset_middle_sep = 0;
if (first_expanded && second_expanded) {
no_offset_middle_sep = get_size()[axis] * ratio - sep / 2;
@@ -104,12 +93,13 @@ void SplitContainer::_resort() {
no_offset_middle_sep = ms_first[axis];
}
- middle_sep = no_offset_middle_sep;
- middle_sep += (collapsed) ? 0 : split_offset;
- middle_sep = MIN(middle_sep, get_size()[axis] - ms_second[axis] - sep);
- middle_sep = MAX(middle_sep, ms_first[axis]);
- if (!collapsed) {
- split_offset = middle_sep - no_offset_middle_sep;
+ // Compute the final middle separation
+ int clamped_split_offset = CLAMP(split_offset, ms_first[axis] - no_offset_middle_sep, (get_size()[axis] - ms_second[axis] - sep) - no_offset_middle_sep);
+ middle_sep = no_offset_middle_sep + clamped_split_offset;
+ if (!collapsed && should_clamp_split_offset) {
+ split_offset = clamped_split_offset;
+ _change_notify("split_offset");
+ should_clamp_split_offset = false;
}
if (vertical) {
@@ -123,7 +113,6 @@ void SplitContainer::_resort() {
}
update();
- _change_notify("split_offset");
}
Size2 SplitContainer::get_minimum_size() const {
@@ -131,8 +120,8 @@ Size2 SplitContainer::get_minimum_size() const {
/* Calculate MINIMUM SIZE */
Size2i minimum;
- int sep = get_constant("separation");
Ref<Texture> g = get_icon("grabber");
+ int sep = get_constant("separation");
sep = (dragger_visibility != DRAGGER_HIDDEN_COLLAPSED) ? MAX(sep, vertical ? g->get_height() : g->get_width()) : 0;
for (int i = 0; i < 2; i++) {
@@ -248,6 +237,7 @@ void SplitContainer::_gui_input(const Ref<InputEvent> &p_event) {
if (mm.is_valid() && dragging) {
split_offset = drag_ofs + ((vertical ? mm->get_position().y : mm->get_position().x) - drag_from);
+ should_clamp_split_offset = true;
queue_sort();
emit_signal("dragged", get_split_offset());
}
@@ -282,6 +272,7 @@ void SplitContainer::set_split_offset(int p_offset) {
return;
split_offset = p_offset;
+
queue_sort();
}
@@ -290,6 +281,12 @@ int SplitContainer::get_split_offset() const {
return split_offset;
}
+void SplitContainer::clamp_split_offset() {
+ should_clamp_split_offset = true;
+
+ queue_sort();
+}
+
void SplitContainer::set_collapsed(bool p_collapsed) {
if (collapsed == p_collapsed)
@@ -319,8 +316,10 @@ bool SplitContainer::is_collapsed() const {
void SplitContainer::_bind_methods() {
ClassDB::bind_method(D_METHOD("_gui_input"), &SplitContainer::_gui_input);
+
ClassDB::bind_method(D_METHOD("set_split_offset", "offset"), &SplitContainer::set_split_offset);
ClassDB::bind_method(D_METHOD("get_split_offset"), &SplitContainer::get_split_offset);
+ ClassDB::bind_method(D_METHOD("clamp_split_offset"), &SplitContainer::clamp_split_offset);
ClassDB::bind_method(D_METHOD("set_collapsed", "collapsed"), &SplitContainer::set_collapsed);
ClassDB::bind_method(D_METHOD("is_collapsed"), &SplitContainer::is_collapsed);
@@ -343,6 +342,7 @@ SplitContainer::SplitContainer(bool p_vertical) {
mouse_inside = false;
split_offset = 0;
+ should_clamp_split_offset = false;
middle_sep = 0;
vertical = p_vertical;
dragging = false;
diff --git a/scene/gui/split_container.h b/scene/gui/split_container.h
index 321f7fd3b7..f8b3343aa8 100644
--- a/scene/gui/split_container.h
+++ b/scene/gui/split_container.h
@@ -45,9 +45,10 @@ public:
};
private:
- bool vertical;
+ bool should_clamp_split_offset;
int split_offset;
int middle_sep;
+ bool vertical;
bool dragging;
int drag_from;
int drag_ofs;
@@ -67,6 +68,7 @@ protected:
public:
void set_split_offset(int p_offset);
int get_split_offset() const;
+ void clamp_split_offset();
void set_collapsed(bool p_collapsed);
bool is_collapsed() const;
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index c083e727d1..f441364c44 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -1419,7 +1419,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
while (c) {
- if (cache.draw_relationship_lines == 1 && (c->get_parent() != root || !hide_root)) {
+ if (cache.draw_relationship_lines == 1 && (!hide_root || c->parent != root)) {
int root_ofs = children_pos.x + ((p_item->disable_folding || hide_folding) ? cache.hseparation : cache.item_margin);
int parent_ofs = p_pos.x + ((p_item->disable_folding || hide_folding) ? cache.hseparation : cache.item_margin);
Point2i root_pos = Point2i(root_ofs, children_pos.y + label_h / 2) - cache.offset + p_draw_ofs;
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index ae2ab2af80..ea50e7289d 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -1008,6 +1008,32 @@ void Node::_validate_child_name(Node *p_child, bool p_force_human_readable) {
}
}
+// Return s + 1 as if it were an integer
+String increase_numeric_string(const String &s) {
+
+ String res = s;
+ bool carry = res.length() > 0;
+
+ for (int i = res.length() - 1; i >= 0; i--) {
+ if (!carry) {
+ break;
+ }
+ CharType n = s[i];
+ if (n == '9') { // keep carry as true: 9 + 1
+ res[i] = '0';
+ } else {
+ res[i] = s[i] + 1;
+ carry = false;
+ }
+ }
+
+ if (carry) {
+ res = "1" + res;
+ }
+
+ return res;
+}
+
String Node::_generate_serial_child_name(Node *p_child) {
String name = p_child->data.name;
@@ -1040,42 +1066,38 @@ String Node::_generate_serial_child_name(Node *p_child) {
}
String nnsep = _get_name_num_separator();
- int num = 0;
- bool explicit_zero = false;
- if (nums.length() > 0 && name.substr(name.length() - nnsep.length() - nums.length(), nnsep.length()) == nnsep) {
- // Base name + Separator + Number
- num = nums.to_int();
- name = name.substr(0, name.length() - nnsep.length() - nums.length()); // Keep base name
- if (num == 0) {
- explicit_zero = true;
+ int name_last_index = name.length() - nnsep.length() - nums.length();
+
+ // Assign the base name + separator to name if we have numbers preceded by a separator
+ if (nums.length() > 0 && name.substr(name_last_index, nnsep.length()) == nnsep) {
+ name = name.substr(0, name_last_index + nnsep.length()).strip_edges();
+ } else {
+ nums = "";
+ }
+
+ Vector<String> children_names;
+
+ for (int i = 0; i < data.children.size(); i++) {
+ String child_name = data.children[i]->data.name;
+ if (data.children[i] == p_child)
+ continue;
+ if (child_name.begins_with(name)) {
+ children_names.push_back(child_name);
}
}
- int num_places = nums.length();
for (;;) {
- String attempt = (name + (num > 0 || explicit_zero ? nnsep + itos(num).pad_zeros(num_places) : "")).strip_edges();
- bool found = false;
- for (int i = 0; i < data.children.size(); i++) {
- if (data.children[i] == p_child)
- continue;
- if (data.children[i]->data.name == attempt) {
- found = true;
- break;
- }
- }
- if (!found) {
+ String attempt = name + nums;
+
+ if (children_names.find(attempt) == -1) {
return attempt;
} else {
- if (num == 0) {
- if (explicit_zero) {
- // Name ended in separator + 0; user expects to get to separator + 1
- num = 1;
- } else {
- // Name was undecorated so skip to 2 for a more natural result
- num = 2;
- }
+ if (nums.length() == 0) {
+ // Name was undecorated so skip to 2 for a more natural result
+ nums = "2";
+ name += nnsep; // Add separator because nums.length() > 0 was false
} else {
- num++;
+ nums = increase_numeric_string(nums);
}
}
}
diff --git a/scene/resources/dynamic_font.cpp b/scene/resources/dynamic_font.cpp
index d6b40766a2..ad22d6530c 100644
--- a/scene/resources/dynamic_font.cpp
+++ b/scene/resources/dynamic_font.cpp
@@ -82,11 +82,14 @@ void DynamicFontData::set_force_autohinter(bool p_force) {
}
void DynamicFontData::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_antialiased", "antialiased"), &DynamicFontData::set_antialiased);
+ ClassDB::bind_method(D_METHOD("is_antialiased"), &DynamicFontData::is_antialiased);
ClassDB::bind_method(D_METHOD("set_font_path", "path"), &DynamicFontData::set_font_path);
ClassDB::bind_method(D_METHOD("get_font_path"), &DynamicFontData::get_font_path);
ClassDB::bind_method(D_METHOD("set_hinting", "mode"), &DynamicFontData::set_hinting);
ClassDB::bind_method(D_METHOD("get_hinting"), &DynamicFontData::get_hinting);
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "antialiased"), "set_antialiased", "is_antialiased");
ADD_PROPERTY(PropertyInfo(Variant::INT, "hinting", PROPERTY_HINT_ENUM, "None,Light,Normal"), "set_hinting", "get_hinting");
BIND_ENUM_CONSTANT(HINTING_NONE);
@@ -98,6 +101,7 @@ void DynamicFontData::_bind_methods() {
DynamicFontData::DynamicFontData() {
+ antialiased = true;
force_autohinter = false;
hinting = DynamicFontData::HINTING_NORMAL;
font_mem = NULL;
@@ -632,7 +636,7 @@ void DynamicFontAtSize::_update_char(CharType p_char) {
if (id.outline_size > 0) {
character = _make_outline_char(p_char);
} else {
- error = FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL);
+ error = FT_Render_Glyph(face->glyph, font->antialiased ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO);
if (!error)
character = _bitmap_to_character(slot->bitmap, slot->bitmap_top, slot->bitmap_left, slot->advance.x / 64.0);
}
@@ -785,6 +789,18 @@ void DynamicFont::set_use_filter(bool p_enable) {
_reload_cache();
}
+bool DynamicFontData::is_antialiased() const {
+
+ return antialiased;
+}
+
+void DynamicFontData::set_antialiased(bool p_antialiased) {
+
+ if (antialiased == p_antialiased)
+ return;
+ antialiased = p_antialiased;
+}
+
DynamicFontData::Hinting DynamicFontData::get_hinting() const {
return hinting;
diff --git a/scene/resources/dynamic_font.h b/scene/resources/dynamic_font.h
index bd3f84d62c..96437e8982 100644
--- a/scene/resources/dynamic_font.h
+++ b/scene/resources/dynamic_font.h
@@ -71,12 +71,15 @@ public:
HINTING_NORMAL
};
+ bool is_antialiased() const;
+ void set_antialiased(bool p_antialiased);
Hinting get_hinting() const;
void set_hinting(Hinting p_hinting);
private:
const uint8_t *font_mem;
int font_mem_size;
+ bool antialiased;
bool force_autohinter;
Hinting hinting;
diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp
index 8ff08f91f2..5327ed318f 100644
--- a/scene/resources/material.cpp
+++ b/scene/resources/material.cpp
@@ -699,7 +699,7 @@ void SpatialMaterial::_update_shader() {
if (features[FEATURE_DEPTH_MAPPING] && !flags[FLAG_UV1_USE_TRIPLANAR]) { //depthmap not supported with triplanar
code += "\t{\n";
- code += "\t\tvec3 view_dir = normalize(normalize(-VERTEX)*mat3(TANGENT*depth_flip.x,BINORMAL*depth_flip.y,NORMAL));\n"; //binormal is negative due to mikktpsace
+ code += "\t\tvec3 view_dir = normalize(normalize(-VERTEX)*mat3(TANGENT*depth_flip.x,BINORMAL*depth_flip.y,NORMAL));\n"; // binormal is negative due to mikktspace
if (deep_parallax) {
code += "\t\tfloat num_layers = mix(float(depth_max_layers),float(depth_min_layers), abs(dot(vec3(0.0, 0.0, 1.0), view_dir)));\n";
@@ -2277,7 +2277,7 @@ SpatialMaterial::SpatialMaterial() :
deep_parallax = false;
depth_parallax_flip_tangent = false;
- depth_parallax_flip_binormal = true;
+ depth_parallax_flip_binormal = false;
set_depth_deep_parallax_min_layers(8);
set_depth_deep_parallax_max_layers(32);
set_depth_deep_parallax_flip_tangent(false); //also sets binormal
diff --git a/scene/resources/primitive_meshes.cpp b/scene/resources/primitive_meshes.cpp
index 4906ceb2eb..dafdddd990 100644
--- a/scene/resources/primitive_meshes.cpp
+++ b/scene/resources/primitive_meshes.cpp
@@ -306,7 +306,7 @@ void CapsuleMesh::_create_mesh_array(Array &p_arr) const {
Vector3 p = Vector3(x * radius * w, y * radius * w, z);
points.push_back(p + Vector3(0.0, 0.0, 0.5 * mid_height));
normals.push_back(p.normalized());
- ADD_TANGENT(y, -x, 0.0, -1.0)
+ ADD_TANGENT(-y, x, 0.0, -1.0)
uvs.push_back(Vector2(u, v * onethird));
point++;
@@ -345,7 +345,7 @@ void CapsuleMesh::_create_mesh_array(Array &p_arr) const {
Vector3 p = Vector3(x * radius, y * radius, z);
points.push_back(p);
normals.push_back(Vector3(x, y, 0.0));
- ADD_TANGENT(y, -x, 0.0, -1.0)
+ ADD_TANGENT(-y, x, 0.0, -1.0)
uvs.push_back(Vector2(u, onethird + (v * onethird)));
point++;
@@ -385,7 +385,7 @@ void CapsuleMesh::_create_mesh_array(Array &p_arr) const {
Vector3 p = Vector3(x * radius * w, y * radius * w, z);
points.push_back(p + Vector3(0.0, 0.0, -0.5 * mid_height));
normals.push_back(p.normalized());
- ADD_TANGENT(y, -x, 0.0, -1.0)
+ ADD_TANGENT(-y, x, 0.0, -1.0)
uvs.push_back(Vector2(u, twothirds + ((v - 1.0) * onethird)));
point++;
@@ -514,14 +514,14 @@ void CubeMesh::_create_mesh_array(Array &p_arr) const {
// front
points.push_back(Vector3(x, -y, -start_pos.z)); // double negative on the Z!
normals.push_back(Vector3(0.0, 0.0, 1.0));
- ADD_TANGENT(-1.0, 0.0, 0.0, -1.0);
+ ADD_TANGENT(1.0, 0.0, 0.0, -1.0);
uvs.push_back(Vector2(u, v));
point++;
// back
points.push_back(Vector3(-x, -y, start_pos.z));
normals.push_back(Vector3(0.0, 0.0, -1.0));
- ADD_TANGENT(1.0, 0.0, 0.0, -1.0);
+ ADD_TANGENT(-1.0, 0.0, 0.0, -1.0);
uvs.push_back(Vector2(twothirds + u, v));
point++;
@@ -568,14 +568,14 @@ void CubeMesh::_create_mesh_array(Array &p_arr) const {
// right
points.push_back(Vector3(-start_pos.x, -y, -z));
normals.push_back(Vector3(1.0, 0.0, 0.0));
- ADD_TANGENT(0.0, 0.0, 1.0, -1.0);
+ ADD_TANGENT(0.0, 0.0, -1.0, -1.0);
uvs.push_back(Vector2(onethird + u, v));
point++;
// left
points.push_back(Vector3(start_pos.x, -y, z));
normals.push_back(Vector3(-1.0, 0.0, 0.0));
- ADD_TANGENT(0.0, 0.0, -1.0, -1.0);
+ ADD_TANGENT(0.0, 0.0, 1.0, -1.0);
uvs.push_back(Vector2(u, 0.5 + v));
point++;
@@ -622,14 +622,14 @@ void CubeMesh::_create_mesh_array(Array &p_arr) const {
// top
points.push_back(Vector3(-x, -start_pos.y, -z));
normals.push_back(Vector3(0.0, 1.0, 0.0));
- ADD_TANGENT(1.0, 0.0, 0.0, -1.0);
+ ADD_TANGENT(-1.0, 0.0, 0.0, -1.0);
uvs.push_back(Vector2(onethird + u, 0.5 + v));
point++;
// bottom
points.push_back(Vector3(x, start_pos.y, -z));
normals.push_back(Vector3(0.0, -1.0, 0.0));
- ADD_TANGENT(-1.0, 0.0, 0.0, -1.0);
+ ADD_TANGENT(1.0, 0.0, 0.0, -1.0);
uvs.push_back(Vector2(twothirds + u, 0.5 + v));
point++;
@@ -773,7 +773,7 @@ void CylinderMesh::_create_mesh_array(Array &p_arr) const {
Vector3 p = Vector3(x * radius, y, z * radius);
points.push_back(p);
normals.push_back(Vector3(x, 0.0, z));
- ADD_TANGENT(-z, 0.0, x, -1.0)
+ ADD_TANGENT(z, 0.0, -x, -1.0)
uvs.push_back(Vector2(u, v * 0.5));
point++;
@@ -799,7 +799,7 @@ void CylinderMesh::_create_mesh_array(Array &p_arr) const {
thisrow = point;
points.push_back(Vector3(0.0, y, 0.0));
normals.push_back(Vector3(0.0, 1.0, 0.0));
- ADD_TANGENT(1.0, 0.0, 0.0, 1.0)
+ ADD_TANGENT(1.0, 0.0, 0.0, -1.0)
uvs.push_back(Vector2(0.25, 0.75));
point++;
@@ -816,7 +816,7 @@ void CylinderMesh::_create_mesh_array(Array &p_arr) const {
Vector3 p = Vector3(x * top_radius, y, z * top_radius);
points.push_back(p);
normals.push_back(Vector3(0.0, 1.0, 0.0));
- ADD_TANGENT(1.0, 0.0, 0.0, 1.0)
+ ADD_TANGENT(1.0, 0.0, 0.0, -1.0)
uvs.push_back(Vector2(u, v));
point++;
@@ -835,7 +835,7 @@ void CylinderMesh::_create_mesh_array(Array &p_arr) const {
thisrow = point;
points.push_back(Vector3(0.0, y, 0.0));
normals.push_back(Vector3(0.0, -1.0, 0.0));
- ADD_TANGENT(-1.0, 0.0, 0.0, -1.0)
+ ADD_TANGENT(1.0, 0.0, 0.0, -1.0)
uvs.push_back(Vector2(0.75, 0.75));
point++;
@@ -852,7 +852,7 @@ void CylinderMesh::_create_mesh_array(Array &p_arr) const {
Vector3 p = Vector3(x * bottom_radius, y, z * bottom_radius);
points.push_back(p);
normals.push_back(Vector3(0.0, -1.0, 0.0));
- ADD_TANGENT(-1.0, 0.0, 0.0, -1.0)
+ ADD_TANGENT(1.0, 0.0, 0.0, -1.0)
uvs.push_back(Vector2(u, v));
point++;
@@ -983,7 +983,7 @@ void PlaneMesh::_create_mesh_array(Array &p_arr) const {
points.push_back(Vector3(-x, 0.0, -z));
normals.push_back(Vector3(0.0, 1.0, 0.0));
ADD_TANGENT(1.0, 0.0, 0.0, -1.0);
- uvs.push_back(Vector2(u, v));
+ uvs.push_back(Vector2(1.0 - u, 1.0 - v)); /* 1.0 - uv to match orientation with Quad */
point++;
if (i > 0 && j > 0) {
@@ -1108,14 +1108,14 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const {
/* front */
points.push_back(Vector3(start_x + x, -y, -start_pos.z)); // double negative on the Z!
normals.push_back(Vector3(0.0, 0.0, 1.0));
- ADD_TANGENT(-1.0, 0.0, 0.0, -1.0);
+ ADD_TANGENT(1.0, 0.0, 0.0, -1.0);
uvs.push_back(Vector2(offset_front + u, v));
point++;
/* back */
points.push_back(Vector3(start_x + scaled_size_x - x, -y, start_pos.z));
normals.push_back(Vector3(0.0, 0.0, -1.0));
- ADD_TANGENT(1.0, 0.0, 0.0, -1.0);
+ ADD_TANGENT(-1.0, 0.0, 0.0, -1.0);
uvs.push_back(Vector2(twothirds + offset_back + u, v));
point++;
@@ -1187,14 +1187,14 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const {
/* right */
points.push_back(Vector3(right, -y, -z));
normals.push_back(normal_right);
- ADD_TANGENT(0.0, 0.0, 1.0, -1.0);
+ ADD_TANGENT(0.0, 0.0, -1.0, -1.0);
uvs.push_back(Vector2(onethird + u, v));
point++;
/* left */
points.push_back(Vector3(left, -y, z));
normals.push_back(normal_left);
- ADD_TANGENT(0.0, 0.0, -1.0, -1.0);
+ ADD_TANGENT(0.0, 0.0, 1.0, -1.0);
uvs.push_back(Vector2(u, 0.5 + v));
point++;
@@ -1241,7 +1241,7 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const {
/* bottom */
points.push_back(Vector3(x, start_pos.y, -z));
normals.push_back(Vector3(0.0, -1.0, 0.0));
- ADD_TANGENT(-1.0, 0.0, 0.0, -1.0);
+ ADD_TANGENT(1.0, 0.0, 0.0, -1.0);
uvs.push_back(Vector2(twothirds + u, 0.5 + v));
point++;
@@ -1382,7 +1382,7 @@ void QuadMesh::_create_mesh_array(Array &p_arr) const {
tangents.set(i * 4 + 0, 1.0);
tangents.set(i * 4 + 1, 0.0);
tangents.set(i * 4 + 2, 0.0);
- tangents.set(i * 4 + 3, 1.0);
+ tangents.set(i * 4 + 3, -1.0);
static const Vector2 quad_uv[4] = {
Vector2(0, 1),
@@ -1468,7 +1468,7 @@ void SphereMesh::_create_mesh_array(Array &p_arr) const {
points.push_back(p);
normals.push_back(p.normalized());
};
- ADD_TANGENT(-z, 0.0, x, -1.0)
+ ADD_TANGENT(z, 0.0, -x, -1.0)
uvs.push_back(Vector2(u, v));
point++;
diff --git a/servers/audio/audio_rb_resampler.cpp b/servers/audio/audio_rb_resampler.cpp
index 84a87de2e2..d9b3579812 100644
--- a/servers/audio/audio_rb_resampler.cpp
+++ b/servers/audio/audio_rb_resampler.cpp
@@ -79,53 +79,27 @@ uint32_t AudioRBResampler::_resample(AudioFrame *p_dest, int p_todo, int32_t p_i
p_dest[i] = AudioFrame(v0, v1);
}
- // For now, channels higher than stereo are almost ignored
+ // This will probably never be used, but added anyway
if (C == 4) {
- // FIXME: v2 and v3 are not being used (thus were commented out to prevent
- // compilation warnings, but they should likely be uncommented *and* used).
- // See also C == 6 with similar issues.
float v0 = rb[(pos << 2) + 0];
float v1 = rb[(pos << 2) + 1];
- /*
- float v2 = rb[(pos << 2) + 2];
- float v3 = rb[(pos << 2) + 3];
- */
float v0n = rb[(pos_next << 2) + 0];
float v1n = rb[(pos_next << 2) + 1];
- /*
- float v2n = rb[(pos_next << 2) + 2];
- float v3n = rb[(pos_next << 2) + 3];
- */
-
v0 += (v0n - v0) * frac;
v1 += (v1n - v1) * frac;
- /*
- v2 += (v2n - v2) * frac;
- v3 += (v3n - v3) * frac;
- */
p_dest[i] = AudioFrame(v0, v1);
}
if (C == 6) {
- // FIXME: Lot of unused assignments here, but it seems like intermediate calculations
- // should be done as for C == 2 (C == 4 also has some unused assignments).
float v0 = rb[(pos * 6) + 0];
float v1 = rb[(pos * 6) + 1];
- /*
- float v2 = rb[(pos * 6) + 2];
- float v3 = rb[(pos * 6) + 3];
- float v4 = rb[(pos * 6) + 4];
- float v5 = rb[(pos * 6) + 5];
float v0n = rb[(pos_next * 6) + 0];
float v1n = rb[(pos_next * 6) + 1];
- float v2n = rb[(pos_next * 6) + 2];
- float v3n = rb[(pos_next * 6) + 3];
- float v4n = rb[(pos_next * 6) + 4];
- float v5n = rb[(pos_next * 6) + 5];
- */
+ v0 += (v0n - v0) * frac;
+ v1 += (v1n - v1) * frac;
p_dest[i] = AudioFrame(v0, v1);
}
}
diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp
index 358ed8ca54..50e45963d9 100644
--- a/servers/visual/shader_language.cpp
+++ b/servers/visual/shader_language.cpp
@@ -131,7 +131,6 @@ const char *ShaderLanguage::token_names[TK_MAX] = {
"TYPE_USAMPLER3D",
"TYPE_SAMPLERCUBE",
"INTERPOLATION_FLAT",
- "INTERPOLATION_NO_PERSPECTIVE",
"INTERPOLATION_SMOOTH",
"PRECISION_LOW",
"PRECISION_MID",
@@ -271,7 +270,6 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = {
{ TK_TYPE_USAMPLER3D, "usampler3D" },
{ TK_TYPE_SAMPLERCUBE, "samplerCube" },
{ TK_INTERPOLATION_FLAT, "flat" },
- { TK_INTERPOLATION_NO_PERSPECTIVE, "noperspective" },
{ TK_INTERPOLATION_SMOOTH, "smooth" },
{ TK_PRECISION_LOW, "lowp" },
{ TK_PRECISION_MID, "mediump" },
@@ -759,7 +757,6 @@ bool ShaderLanguage::is_token_interpolation(TokenType p_type) {
return (
p_type == TK_INTERPOLATION_FLAT ||
- p_type == TK_INTERPOLATION_NO_PERSPECTIVE ||
p_type == TK_INTERPOLATION_SMOOTH);
}
@@ -767,8 +764,6 @@ ShaderLanguage::DataInterpolation ShaderLanguage::get_token_interpolation(TokenT
if (p_type == TK_INTERPOLATION_FLAT)
return INTERPOLATION_FLAT;
- else if (p_type == TK_INTERPOLATION_NO_PERSPECTIVE)
- return INTERPOLATION_NO_PERSPECTIVE;
else
return INTERPOLATION_SMOOTH;
}
diff --git a/servers/visual/shader_language.h b/servers/visual/shader_language.h
index b51106fad7..2d1851928e 100644
--- a/servers/visual/shader_language.h
+++ b/servers/visual/shader_language.h
@@ -80,7 +80,6 @@ public:
TK_TYPE_USAMPLER3D,
TK_TYPE_SAMPLERCUBE,
TK_INTERPOLATION_FLAT,
- TK_INTERPOLATION_NO_PERSPECTIVE,
TK_INTERPOLATION_SMOOTH,
TK_PRECISION_LOW,
TK_PRECISION_MID,
@@ -210,7 +209,6 @@ public:
enum DataInterpolation {
INTERPOLATION_FLAT,
- INTERPOLATION_NO_PERSPECTIVE,
INTERPOLATION_SMOOTH,
};
diff --git a/servers/visual/visual_server_canvas.cpp b/servers/visual/visual_server_canvas.cpp
index 74a05ce4e4..734c295a72 100644
--- a/servers/visual/visual_server_canvas.cpp
+++ b/servers/visual/visual_server_canvas.cpp
@@ -51,7 +51,7 @@ void VisualServerCanvas::_render_canvas_item_tree(Item *p_canvas_item, const Tra
}
}
-void _collect_ysort_children(VisualServerCanvas::Item *p_canvas_item, Transform2D p_transform, VisualServerCanvas::Item **r_items, Transform2D *r_extra_transforms, int &r_index) {
+void _collect_ysort_children(VisualServerCanvas::Item *p_canvas_item, Transform2D p_transform, VisualServerCanvas::Item **r_items, int &r_index) {
int child_item_count = p_canvas_item->child_items.size();
VisualServerCanvas::Item **child_items = p_canvas_item->child_items.ptrw();
for (int i = 0; i < child_item_count; i++) {
@@ -64,7 +64,7 @@ void _collect_ysort_children(VisualServerCanvas::Item *p_canvas_item, Transform2
r_index++;
if (child_items[i]->sort_y)
- _collect_ysort_children(child_items[i], p_transform * child_items[i]->xform, r_items, r_extra_transforms, r_index);
+ _collect_ysort_children(child_items[i], p_transform * child_items[i]->xform, r_items, r_index);
}
}
@@ -100,7 +100,6 @@ void VisualServerCanvas::_render_canvas_item(Item *p_canvas_item, const Transfor
int child_item_count = ci->child_items.size();
Item **child_items = ci->child_items.ptrw();
- Transform2D *child_extra_transforms = NULL;
if (ci->clip) {
if (p_canvas_clip != NULL) {
@@ -118,14 +117,14 @@ void VisualServerCanvas::_render_canvas_item(Item *p_canvas_item, const Transfor
if (ci->ysort_children_count == -1) {
ci->ysort_children_count = 0;
- _collect_ysort_children(ci, Transform2D(), NULL, NULL, ci->ysort_children_count);
+ _collect_ysort_children(ci, Transform2D(), NULL, ci->ysort_children_count);
}
child_item_count = ci->ysort_children_count;
child_items = (Item **)alloca(child_item_count * sizeof(Item *));
int i = 0;
- _collect_ysort_children(ci, Transform2D(), child_items, child_extra_transforms, i);
+ _collect_ysort_children(ci, Transform2D(), child_items, i);
SortArray<Item *, ItemPtrSort> sorter;
sorter.sort(child_items, child_item_count);
@@ -336,7 +335,12 @@ void VisualServerCanvas::canvas_item_set_parent(RID p_item, RID p_parent) {
Item *item_owner = canvas_item_owner.get(canvas_item->parent);
item_owner->child_items.erase(canvas_item);
- item_owner->ysort_children_count = -1;
+
+ Item *ysort_owner = item_owner;
+ while (ysort_owner && ysort_owner->sort_y) {
+ item_owner->ysort_children_count = -1;
+ ysort_owner = canvas_item_owner.getornull(ysort_owner->parent);
+ }
}
canvas_item->parent = RID();
@@ -1346,6 +1350,12 @@ bool VisualServerCanvas::free(RID p_rid) {
Item *item_owner = canvas_item_owner.get(canvas_item->parent);
item_owner->child_items.erase(canvas_item);
+
+ Item *ysort_owner = item_owner;
+ while (ysort_owner && ysort_owner->sort_y) {
+ item_owner->ysort_children_count = -1;
+ ysort_owner = canvas_item_owner.getornull(ysort_owner->parent);
+ }
}
}
diff --git a/thirdparty/enet/godot.cpp b/thirdparty/enet/godot.cpp
index 6ba7cf0000..73a09f9b1d 100644
--- a/thirdparty/enet/godot.cpp
+++ b/thirdparty/enet/godot.cpp
@@ -33,7 +33,7 @@
*/
#include "core/io/ip.h"
-#include "core/io/packet_peer_udp.h"
+#include "core/io/net_socket.h"
#include "core/os/os.h"
// This must be last for windows to compile (tested with MinGW)
@@ -90,6 +90,16 @@ int enet_address_get_host(const ENetAddress *address, char *name, size_t nameLen
return -1;
}
+ENetSocket enet_socket_create(ENetSocketType type) {
+
+ NetSocket *socket = NetSocket::create();
+ IP::Type ip_type = IP::TYPE_ANY;
+ socket->open(NetSocket::TYPE_UDP, ip_type);
+ socket->set_blocking_enabled(false);
+
+ return socket;
+}
+
int enet_socket_bind(ENetSocket socket, const ENetAddress *address) {
IP_Address ip;
@@ -99,23 +109,15 @@ int enet_socket_bind(ENetSocket socket, const ENetAddress *address) {
ip.set_ipv6(address->host);
}
- PacketPeerUDP *sock = (PacketPeerUDP *)socket;
- if (sock->listen(address->port, ip) != OK) {
+ NetSocket *sock = (NetSocket *)socket;
+ if (sock->bind(ip, address->port) != OK) {
return -1;
}
return 0;
}
-ENetSocket enet_socket_create(ENetSocketType type) {
-
- PacketPeerUDP *socket = memnew(PacketPeerUDP);
- socket->set_blocking_mode(false);
-
- return socket;
-}
-
void enet_socket_destroy(ENetSocket socket) {
- PacketPeerUDP *sock = (PacketPeerUDP *)socket;
+ NetSocket *sock = (NetSocket *)socket;
sock->close();
memdelete(sock);
}
@@ -124,13 +126,12 @@ int enet_socket_send(ENetSocket socket, const ENetAddress *address, const ENetBu
ERR_FAIL_COND_V(address == NULL, -1);
- PacketPeerUDP *sock = (PacketPeerUDP *)socket;
+ NetSocket *sock = (NetSocket *)socket;
IP_Address dest;
Error err;
size_t i = 0;
dest.set_ipv6(address->host);
- sock->set_dest_address(dest, address->port);
// Create a single packet.
PoolVector<uint8_t> out;
@@ -148,7 +149,8 @@ int enet_socket_send(ENetSocket socket, const ENetAddress *address, const ENetBu
pos += buffers[i].dataLength;
}
- err = sock->put_packet((const uint8_t *)&w[0], size);
+ int sent = 0;
+ err = sock->sendto((const uint8_t *)&w[0], size, sent, dest, address->port);
if (err != OK) {
if (err == ERR_BUSY) { // Blocking call
@@ -159,32 +161,36 @@ int enet_socket_send(ENetSocket socket, const ENetAddress *address, const ENetBu
return -1;
}
- return size;
+ return sent;
}
int enet_socket_receive(ENetSocket socket, ENetAddress *address, ENetBuffer *buffers, size_t bufferCount) {
ERR_FAIL_COND_V(bufferCount != 1, -1);
- PacketPeerUDP *sock = (PacketPeerUDP *)socket;
+ NetSocket *sock = (NetSocket *)socket;
- int pc = sock->get_available_packet_count();
- if (pc < 1) {
- return pc;
- }
+ Error ret = sock->poll(NetSocket::POLL_TYPE_IN, 0);
- const uint8_t *buffer;
- int buffer_size;
- Error err = sock->get_packet(&buffer, buffer_size);
- if (err)
+ if (ret == ERR_BUSY)
+ return 0;
+
+ if (ret != OK)
return -1;
- copymem(buffers[0].data, buffer, buffer_size);
+ int read;
+ IP_Address ip;
- enet_address_set_ip(address, sock->get_packet_address().get_ipv6(), 16);
- address->port = sock->get_packet_port();
+ Error err = sock->recvfrom((uint8_t *)buffers[0].data, buffers[0].dataLength, read, ip, address->port);
+ if (err == ERR_BUSY)
+ return 0;
+
+ if (err != OK)
+ return -1;
+
+ enet_address_set_ip(address, ip.get_ipv6(), 16);
- return buffer_size;
+ return read;
}
// Not implemented