Merge pull request #56730 from akien-mga/3.x-cherrypicks

This commit is contained in:
Rémi Verschelde 2022-01-12 18:44:11 +01:00 committed by GitHub
commit 2d645edacc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
44 changed files with 189 additions and 220 deletions

View File

@ -498,8 +498,9 @@ if selected_platform in platform_list:
if env["target"] == "release": if env["target"] == "release":
if env["tools"]: if env["tools"]:
print("Tools can only be built with targets 'debug' and 'release_debug'.") print("ERROR: The editor can only be built with `target=debug` or `target=release_debug`.")
sys.exit(255) print(" Use `tools=no target=release` to build a release export template.")
Exit(255)
suffix += ".opt" suffix += ".opt"
env.Append(CPPDEFINES=["NDEBUG"]) env.Append(CPPDEFINES=["NDEBUG"])

View File

@ -82,11 +82,6 @@ bool AABB::create_from_points(const Vector<Vector3> &p_points) {
} }
void AABB::merge_with(const AABB &p_aabb) { void AABB::merge_with(const AABB &p_aabb) {
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0 || size.z < 0 || p_aabb.size.x < 0 || p_aabb.size.y < 0 || p_aabb.size.z < 0)) {
ERR_PRINT("AABB size is negative, this is not supported. Use AABB.abs() to get an AABB with a positive size.");
}
#endif
Vector3 beg_1, beg_2; Vector3 beg_1, beg_2;
Vector3 end_1, end_2; Vector3 end_1, end_2;
Vector3 min, max; Vector3 min, max;
@ -113,11 +108,6 @@ bool AABB::is_equal_approx(const AABB &p_aabb) const {
} }
AABB AABB::intersection(const AABB &p_aabb) const { AABB AABB::intersection(const AABB &p_aabb) const {
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0 || size.z < 0 || p_aabb.size.x < 0 || p_aabb.size.y < 0 || p_aabb.size.z < 0)) {
ERR_PRINT("AABB size is negative, this is not supported. Use AABB.abs() to get an AABB with a positive size.");
}
#endif
Vector3 src_min = position; Vector3 src_min = position;
Vector3 src_max = position + size; Vector3 src_max = position + size;
Vector3 dst_min = p_aabb.position; Vector3 dst_min = p_aabb.position;
@ -150,11 +140,6 @@ AABB AABB::intersection(const AABB &p_aabb) const {
} }
bool AABB::intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *r_clip, Vector3 *r_normal) const { bool AABB::intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *r_clip, Vector3 *r_normal) const {
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0 || size.z < 0)) {
ERR_PRINT("AABB size is negative, this is not supported. Use AABB.abs() to get an AABB with a positive size.");
}
#endif
Vector3 c1, c2; Vector3 c1, c2;
Vector3 end = position + size; Vector3 end = position + size;
real_t near = -1e20; real_t near = -1e20;
@ -198,11 +183,6 @@ bool AABB::intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *
} }
bool AABB::intersects_segment(const Vector3 &p_from, const Vector3 &p_to, Vector3 *r_clip, Vector3 *r_normal) const { bool AABB::intersects_segment(const Vector3 &p_from, const Vector3 &p_to, Vector3 *r_clip, Vector3 *r_normal) const {
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0 || size.z < 0)) {
ERR_PRINT("AABB size is negative, this is not supported. Use AABB.abs() to get an AABB with a positive size.");
}
#endif
real_t min = 0, max = 1; real_t min = 0, max = 1;
int axis = 0; int axis = 0;
real_t sign = 0; real_t sign = 0;

View File

@ -115,11 +115,6 @@ public:
}; };
inline bool AABB::intersects(const AABB &p_aabb) const { inline bool AABB::intersects(const AABB &p_aabb) const {
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0 || size.z < 0 || p_aabb.size.x < 0 || p_aabb.size.y < 0 || p_aabb.size.z < 0)) {
ERR_PRINT("AABB size is negative, this is not supported. Use AABB.abs() to get an AABB with a positive size.");
}
#endif
if (position.x >= (p_aabb.position.x + p_aabb.size.x)) { if (position.x >= (p_aabb.position.x + p_aabb.size.x)) {
return false; return false;
} }
@ -143,11 +138,6 @@ inline bool AABB::intersects(const AABB &p_aabb) const {
} }
inline bool AABB::intersects_inclusive(const AABB &p_aabb) const { inline bool AABB::intersects_inclusive(const AABB &p_aabb) const {
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0 || size.z < 0 || p_aabb.size.x < 0 || p_aabb.size.y < 0 || p_aabb.size.z < 0)) {
ERR_PRINT("AABB size is negative, this is not supported. Use AABB.abs() to get an AABB with a positive size.");
}
#endif
if (position.x > (p_aabb.position.x + p_aabb.size.x)) { if (position.x > (p_aabb.position.x + p_aabb.size.x)) {
return false; return false;
} }
@ -171,11 +161,6 @@ inline bool AABB::intersects_inclusive(const AABB &p_aabb) const {
} }
inline bool AABB::encloses(const AABB &p_aabb) const { inline bool AABB::encloses(const AABB &p_aabb) const {
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0 || size.z < 0 || p_aabb.size.x < 0 || p_aabb.size.y < 0 || p_aabb.size.z < 0)) {
ERR_PRINT("AABB size is negative, this is not supported. Use AABB.abs() to get an AABB with a positive size.");
}
#endif
Vector3 src_min = position; Vector3 src_min = position;
Vector3 src_max = position + size; Vector3 src_max = position + size;
Vector3 dst_min = p_aabb.position; Vector3 dst_min = p_aabb.position;
@ -286,11 +271,6 @@ bool AABB::inside_convex_shape(const Plane *p_planes, int p_plane_count) const {
} }
bool AABB::has_point(const Vector3 &p_point) const { bool AABB::has_point(const Vector3 &p_point) const {
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0 || size.z < 0)) {
ERR_PRINT("AABB size is negative, this is not supported. Use AABB.abs() to get an AABB with a positive size.");
}
#endif
if (p_point.x < position.x) { if (p_point.x < position.x) {
return false; return false;
} }
@ -314,11 +294,6 @@ bool AABB::has_point(const Vector3 &p_point) const {
} }
inline void AABB::expand_to(const Vector3 &p_vector) { inline void AABB::expand_to(const Vector3 &p_vector) {
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0 || size.z < 0)) {
ERR_PRINT("AABB size is negative, this is not supported. Use AABB.abs() to get an AABB with a positive size.");
}
#endif
Vector3 begin = position; Vector3 begin = position;
Vector3 end = position + size; Vector3 end = position + size;
@ -385,11 +360,6 @@ inline real_t AABB::get_shortest_axis_size() const {
} }
bool AABB::smits_intersect_ray(const Vector3 &p_from, const Vector3 &p_dir, real_t t0, real_t t1) const { bool AABB::smits_intersect_ray(const Vector3 &p_from, const Vector3 &p_dir, real_t t0, real_t t1) const {
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0 || size.z < 0)) {
ERR_PRINT("AABB size is negative, this is not supported. Use AABB.abs() to get an AABB with a positive size.");
}
#endif
real_t divx = 1.0 / p_dir.x; real_t divx = 1.0 / p_dir.x;
real_t divy = 1.0 / p_dir.y; real_t divy = 1.0 / p_dir.y;
real_t divz = 1.0 / p_dir.z; real_t divz = 1.0 / p_dir.z;

View File

@ -35,11 +35,6 @@ bool Rect2::is_equal_approx(const Rect2 &p_rect) const {
} }
bool Rect2::intersects_segment(const Point2 &p_from, const Point2 &p_to, Point2 *r_pos, Point2 *r_normal) const { bool Rect2::intersects_segment(const Point2 &p_from, const Point2 &p_to, Point2 *r_pos, Point2 *r_normal) const {
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0)) {
ERR_PRINT("Rect2 size is negative, this is not supported. Use Rect2.abs() to get a Rect2 with a positive size.");
}
#endif
real_t min = 0, max = 1; real_t min = 0, max = 1;
int axis = 0; int axis = 0;
real_t sign = 0; real_t sign = 0;
@ -100,11 +95,6 @@ bool Rect2::intersects_segment(const Point2 &p_from, const Point2 &p_to, Point2
} }
bool Rect2::intersects_transformed(const Transform2D &p_xform, const Rect2 &p_rect) const { bool Rect2::intersects_transformed(const Transform2D &p_xform, const Rect2 &p_rect) const {
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0 || p_rect.size.x < 0 || p_rect.size.y < 0)) {
ERR_PRINT("Rect2 size is negative, this is not supported. Use Rect2.abs() to get a Rect2 with a positive size.");
}
#endif
//SAT intersection between local and transformed rect2 //SAT intersection between local and transformed rect2
Vector2 xf_points[4] = { Vector2 xf_points[4] = {

View File

@ -49,11 +49,6 @@ struct Rect2 {
_FORCE_INLINE_ Vector2 get_center() const { return position + (size * 0.5); } _FORCE_INLINE_ Vector2 get_center() const { return position + (size * 0.5); }
inline bool intersects(const Rect2 &p_rect, const bool p_include_borders = false) const { inline bool intersects(const Rect2 &p_rect, const bool p_include_borders = false) const {
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0 || p_rect.size.x < 0 || p_rect.size.y < 0)) {
ERR_PRINT("Rect2 size is negative, this is not supported. Use Rect2.abs() to get a Rect2 with a positive size.");
}
#endif
if (p_include_borders) { if (p_include_borders) {
if (position.x > (p_rect.position.x + p_rect.size.width)) { if (position.x > (p_rect.position.x + p_rect.size.width)) {
return false; return false;
@ -86,11 +81,6 @@ struct Rect2 {
} }
inline real_t distance_to(const Vector2 &p_point) const { inline real_t distance_to(const Vector2 &p_point) const {
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0)) {
ERR_PRINT("Rect2 size is negative, this is not supported. Use Rect2.abs() to get a Rect2 with a positive size.");
}
#endif
real_t dist = 0.0; real_t dist = 0.0;
bool inside = true; bool inside = true;
@ -127,11 +117,6 @@ struct Rect2 {
bool intersects_segment(const Point2 &p_from, const Point2 &p_to, Point2 *r_pos = nullptr, Point2 *r_normal = nullptr) const; bool intersects_segment(const Point2 &p_from, const Point2 &p_to, Point2 *r_pos = nullptr, Point2 *r_normal = nullptr) const;
inline bool encloses(const Rect2 &p_rect) const { inline bool encloses(const Rect2 &p_rect) const {
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0 || p_rect.size.x < 0 || p_rect.size.y < 0)) {
ERR_PRINT("Rect2 size is negative, this is not supported. Use Rect2.abs() to get a Rect2 with a positive size.");
}
#endif
return (p_rect.position.x >= position.x) && (p_rect.position.y >= position.y) && return (p_rect.position.x >= position.x) && (p_rect.position.y >= position.y) &&
((p_rect.position.x + p_rect.size.x) <= (position.x + size.x)) && ((p_rect.position.x + p_rect.size.x) <= (position.x + size.x)) &&
((p_rect.position.y + p_rect.size.y) <= (position.y + size.y)); ((p_rect.position.y + p_rect.size.y) <= (position.y + size.y));
@ -161,11 +146,7 @@ struct Rect2 {
} }
inline Rect2 merge(const Rect2 &p_rect) const { ///< return a merged rect inline Rect2 merge(const Rect2 &p_rect) const { ///< return a merged rect
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0 || p_rect.size.x < 0 || p_rect.size.y < 0)) {
ERR_PRINT("Rect2 size is negative, this is not supported. Use Rect2.abs() to get a Rect2 with a positive size.");
}
#endif
Rect2 new_rect; Rect2 new_rect;
new_rect.position.x = MIN(p_rect.position.x, position.x); new_rect.position.x = MIN(p_rect.position.x, position.x);
@ -179,11 +160,6 @@ struct Rect2 {
return new_rect; return new_rect;
}; };
inline bool has_point(const Point2 &p_point) const { inline bool has_point(const Point2 &p_point) const {
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0)) {
ERR_PRINT("Rect2 size is negative, this is not supported. Use Rect2.abs() to get a Rect2 with a positive size.");
}
#endif
if (p_point.x < position.x) { if (p_point.x < position.x) {
return false; return false;
} }
@ -206,11 +182,6 @@ struct Rect2 {
bool operator!=(const Rect2 &p_rect) const { return position != p_rect.position || size != p_rect.size; } bool operator!=(const Rect2 &p_rect) const { return position != p_rect.position || size != p_rect.size; }
inline Rect2 grow(real_t p_by) const { inline Rect2 grow(real_t p_by) const {
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0)) {
ERR_PRINT("Rect2 size is negative, this is not supported. Use Rect2.abs() to get a Rect2 with a positive size.");
}
#endif
Rect2 g = *this; Rect2 g = *this;
g.grow_by(p_by); g.grow_by(p_by);
return g; return g;
@ -233,11 +204,6 @@ struct Rect2 {
} }
inline Rect2 grow_individual(real_t p_left, real_t p_top, real_t p_right, real_t p_bottom) const { inline Rect2 grow_individual(real_t p_left, real_t p_top, real_t p_right, real_t p_bottom) const {
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0)) {
ERR_PRINT("Rect2 size is negative, this is not supported. Use Rect2.abs() to get a Rect2 with a positive size.");
}
#endif
Rect2 g = *this; Rect2 g = *this;
g.position.x -= p_left; g.position.x -= p_left;
g.position.y -= p_top; g.position.y -= p_top;
@ -254,11 +220,7 @@ struct Rect2 {
} }
inline void expand_to(const Vector2 &p_vector) { //in place function for speed inline void expand_to(const Vector2 &p_vector) { //in place function for speed
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0)) {
ERR_PRINT("Rect2 size is negative, this is not supported. Use Rect2.abs() to get a Rect2 with a positive size.");
}
#endif
Vector2 begin = position; Vector2 begin = position;
Vector2 end = position + size; Vector2 end = position + size;
@ -311,11 +273,6 @@ struct Rect2i {
_FORCE_INLINE_ Vector2i get_center() const { return position + (size / 2); } _FORCE_INLINE_ Vector2i get_center() const { return position + (size / 2); }
inline bool intersects(const Rect2i &p_rect) const { inline bool intersects(const Rect2i &p_rect) const {
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0 || p_rect.size.x < 0 || p_rect.size.y < 0)) {
ERR_PRINT("Rect2i size is negative, this is not supported. Use Rect2i.abs() to get a Rect2i with a positive size.");
}
#endif
if (position.x > (p_rect.position.x + p_rect.size.width)) { if (position.x > (p_rect.position.x + p_rect.size.width)) {
return false; return false;
} }
@ -333,11 +290,6 @@ struct Rect2i {
} }
inline bool encloses(const Rect2i &p_rect) const { inline bool encloses(const Rect2i &p_rect) const {
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0 || p_rect.size.x < 0 || p_rect.size.y < 0)) {
ERR_PRINT("Rect2i size is negative, this is not supported. Use Rect2i.abs() to get a Rect2i with a positive size.");
}
#endif
return (p_rect.position.x >= position.x) && (p_rect.position.y >= position.y) && return (p_rect.position.x >= position.x) && (p_rect.position.y >= position.y) &&
((p_rect.position.x + p_rect.size.x) < (position.x + size.x)) && ((p_rect.position.x + p_rect.size.x) < (position.x + size.x)) &&
((p_rect.position.y + p_rect.size.y) < (position.y + size.y)); ((p_rect.position.y + p_rect.size.y) < (position.y + size.y));
@ -360,18 +312,14 @@ struct Rect2i {
Point2 p_rect_end = p_rect.position + p_rect.size; Point2 p_rect_end = p_rect.position + p_rect.size;
Point2 end = position + size; Point2 end = position + size;
new_rect.size.x = MIN(p_rect_end.x, end.x) - new_rect.position.x; new_rect.size.x = (int)(MIN(p_rect_end.x, end.x) - new_rect.position.x);
new_rect.size.y = MIN(p_rect_end.y, end.y) - new_rect.position.y; new_rect.size.y = (int)(MIN(p_rect_end.y, end.y) - new_rect.position.y);
return new_rect; return new_rect;
} }
inline Rect2i merge(const Rect2i &p_rect) const { ///< return a merged rect inline Rect2i merge(const Rect2i &p_rect) const { ///< return a merged rect
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0 || p_rect.size.x < 0 || p_rect.size.y < 0)) {
ERR_PRINT("Rect2i size is negative, this is not supported. Use Rect2i.abs() to get a Rect2i with a positive size.");
}
#endif
Rect2i new_rect; Rect2i new_rect;
new_rect.position.x = MIN(p_rect.position.x, position.x); new_rect.position.x = MIN(p_rect.position.x, position.x);
@ -383,13 +331,8 @@ struct Rect2i {
new_rect.size = new_rect.size - new_rect.position; //make relative again new_rect.size = new_rect.size - new_rect.position; //make relative again
return new_rect; return new_rect;
} };
bool has_point(const Point2 &p_point) const { bool has_point(const Point2 &p_point) const {
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0)) {
ERR_PRINT("Rect2i size is negative, this is not supported. Use Rect2i.abs() to get a Rect2i with a positive size.");
}
#endif
if (p_point.x < position.x) { if (p_point.x < position.x) {
return false; return false;
} }
@ -411,11 +354,6 @@ struct Rect2i {
bool operator!=(const Rect2i &p_rect) const { return position != p_rect.position || size != p_rect.size; } bool operator!=(const Rect2i &p_rect) const { return position != p_rect.position || size != p_rect.size; }
Rect2i grow(int p_by) const { Rect2i grow(int p_by) const {
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0)) {
ERR_PRINT("Rect2i size is negative, this is not supported. Use Rect2i.abs() to get a Rect2i with a positive size.");
}
#endif
Rect2i g = *this; Rect2i g = *this;
g.position.x -= p_by; g.position.x -= p_by;
g.position.y -= p_by; g.position.y -= p_by;
@ -434,11 +372,6 @@ struct Rect2i {
} }
inline Rect2i grow_individual(int p_left, int p_top, int p_right, int p_bottom) const { inline Rect2i grow_individual(int p_left, int p_top, int p_right, int p_bottom) const {
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0)) {
ERR_PRINT("Rect2i size is negative, this is not supported. Use Rect2i.abs() to get a Rect2i with a positive size.");
}
#endif
Rect2i g = *this; Rect2i g = *this;
g.position.x -= p_left; g.position.x -= p_left;
g.position.y -= p_top; g.position.y -= p_top;
@ -455,11 +388,6 @@ struct Rect2i {
} }
inline void expand_to(const Point2i &p_vector) { inline void expand_to(const Point2i &p_vector) {
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0)) {
ERR_PRINT("Rect2i size is negative, this is not supported. Use Rect2i.abs() to get a Rect2i with a positive size.");
}
#endif
Point2i begin = position; Point2i begin = position;
Point2i end = position + size; Point2i end = position + size;

View File

@ -85,7 +85,7 @@ enum JoystickList {
JOY_BUTTON_20 = 20, JOY_BUTTON_20 = 20,
JOY_BUTTON_21 = 21, JOY_BUTTON_21 = 21,
JOY_BUTTON_22 = 22, JOY_BUTTON_22 = 22,
JOY_BUTTON_MAX = 23, JOY_BUTTON_MAX = 128, // Android supports up to 36 buttons. DirectInput supports up to 128 buttons.
JOY_L = JOY_BUTTON_4, JOY_L = JOY_BUTTON_4,
JOY_R = JOY_BUTTON_5, JOY_R = JOY_BUTTON_5,

View File

@ -509,6 +509,9 @@ public:
} }
Element *lower_bound(const T &p_value) const { Element *lower_bound(const T &p_value) const {
if (!_data._root) {
return nullptr;
}
return _lower_bound(p_value); return _lower_bound(p_value);
} }

View File

@ -1015,8 +1015,11 @@
<constant name="JOY_BUTTON_22" value="22" enum="JoystickList"> <constant name="JOY_BUTTON_22" value="22" enum="JoystickList">
Gamepad button 22. Gamepad button 22.
</constant> </constant>
<constant name="JOY_BUTTON_MAX" value="23" enum="JoystickList"> <constant name="JOY_BUTTON_MAX" value="128" enum="JoystickList">
Represents the maximum number of joystick buttons supported. The maximum number of game controller buttons supported by the engine. The actual limit may be lower on specific platforms:
- Android: Up to 36 buttons.
- Linux: Up to 80 buttons.
- Windows and macOS: Up to 128 buttons.
</constant> </constant>
<constant name="JOY_SONY_CIRCLE" value="1" enum="JoystickList"> <constant name="JOY_SONY_CIRCLE" value="1" enum="JoystickList">
DualShock circle button. DualShock circle button.

View File

@ -6,7 +6,6 @@
<description> <description>
[AABB] consists of a position, a size, and several utility functions. It is typically used for fast overlap tests. [AABB] consists of a position, a size, and several utility functions. It is typically used for fast overlap tests.
It uses floating-point coordinates. The 2D counterpart to [AABB] is [Rect2]. It uses floating-point coordinates. The 2D counterpart to [AABB] is [Rect2].
Negative values for [member size] are not supported and will not work for most methods. Use [method abs] to get an AABB with a positive size.
[b]Note:[/b] Unlike [Rect2], [AABB] does not have a variant that uses integer coordinates. [b]Note:[/b] Unlike [Rect2], [AABB] does not have a variant that uses integer coordinates.
</description> </description>
<tutorials> <tutorials>

View File

@ -1,10 +1,12 @@
<?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<class name="AudioEffectRecord" inherits="AudioEffect" version="3.5"> <class name="AudioEffectRecord" inherits="AudioEffect" version="3.5">
<brief_description> <brief_description>
Audio effect used for recording sound from a microphone. Audio effect used for recording the sound from an audio bus.
</brief_description> </brief_description>
<description> <description>
Allows the user to record sound from a microphone. It sets and gets the format in which the audio file will be recorded (8-bit, 16-bit, or compressed). It checks whether or not the recording is active, and if it is, records the sound. It then returns the recorded sample. Allows the user to record the sound from an audio bus. This can include all audio output by Godot when used on the "Master" audio bus.
Can be used (with an [AudioStreamMicrophone]) to record from a microphone.
It sets and gets the format in which the audio file will be recorded (8-bit, 16-bit, or compressed). It checks whether or not the recording is active, and if it is, records the sound. It then returns the recorded sample.
</description> </description>
<tutorials> <tutorials>
<link title="Recording with microphone">$DOCS_URL/tutorials/audio/recording_with_microphone.html</link> <link title="Recording with microphone">$DOCS_URL/tutorials/audio/recording_with_microphone.html</link>

View File

@ -893,6 +893,12 @@
<description> <description>
Emitted when the mouse leaves the control's [code]Rect[/code] area, provided its [member mouse_filter] lets the event reach it. Emitted when the mouse leaves the control's [code]Rect[/code] area, provided its [member mouse_filter] lets the event reach it.
[b]Note:[/b] [signal mouse_exited] will be emitted if the mouse enters a child [Control] node, even if the mouse cursor is still inside the parent's [code]Rect[/code] area. [b]Note:[/b] [signal mouse_exited] will be emitted if the mouse enters a child [Control] node, even if the mouse cursor is still inside the parent's [code]Rect[/code] area.
If you want to check whether the mouse truly left the area, ignoring any top nodes, you can use code like this:
[codeblock]
func _on_mouse_exited():
if not Rect2(Vector2(), rect_size).has_point(get_local_mouse_position()):
# Not hovering over area.
[/codeblock]
</description> </description>
</signal> </signal>
<signal name="resized"> <signal name="resized">

View File

@ -13,7 +13,9 @@
<return type="void" /> <return type="void" />
<argument index="0" name="filter" type="String" /> <argument index="0" name="filter" type="String" />
<description> <description>
Adds [code]filter[/code] as a custom filter; [code]filter[/code] should be of the form [code]"filename.extension ; Description"[/code]. For example, [code]"*.png ; PNG Images"[/code]. Adds [code]filter[/code] to the list of filters, which restricts what files can be picked.
A [code]filter[/code] should be of the form [code]"filename.extension ; Description"[/code], where filename and extension can be [code]*[/code] to match any string. Filters starting with [code].[/code] (i.e. empty filenames) are not allowed.
Example filters: [code]"*.png ; PNG Images"[/code], [code]"project.godot ; Godot Project"[/code].
</description> </description>
</method> </method>
<method name="clear_filters"> <method name="clear_filters">
@ -65,7 +67,7 @@
</member> </member>
<member name="dialog_hide_on_ok" type="bool" setter="set_hide_on_ok" getter="get_hide_on_ok" overrides="AcceptDialog" default="false" /> <member name="dialog_hide_on_ok" type="bool" setter="set_hide_on_ok" getter="get_hide_on_ok" overrides="AcceptDialog" default="false" />
<member name="filters" type="PoolStringArray" setter="set_filters" getter="get_filters" default="PoolStringArray( )"> <member name="filters" type="PoolStringArray" setter="set_filters" getter="get_filters" default="PoolStringArray( )">
The available file type filters. For example, this shows only [code].png[/code] and [code].gd[/code] files: [code]set_filters(PoolStringArray(["*.png ; PNG Images","*.gd ; GDScript Files"]))[/code]. The available file type filters. For example, this shows only [code].png[/code] and [code].gd[/code] files: [code]set_filters(PoolStringArray(["*.png ; PNG Images","*.gd ; GDScript Files"]))[/code]. Multiple file types can also be specified in a single filter. [code]"*.png, *.jpg, *.jpeg ; Supported Images"[/code] will show both PNG and JPEG files when selected.
</member> </member>
<member name="mode" type="int" setter="set_mode" getter="get_mode" enum="FileDialog.Mode" default="4"> <member name="mode" type="int" setter="set_mode" getter="get_mode" enum="FileDialog.Mode" default="4">
The dialog's open or save mode, which affects the selection behavior. See enum [code]Mode[/code] constants. The dialog's open or save mode, which affects the selection behavior. See enum [code]Mode[/code] constants.

View File

@ -283,7 +283,7 @@
<theme_item name="port_grab_distance_horizontal" data_type="constant" type="int" default="24"> <theme_item name="port_grab_distance_horizontal" data_type="constant" type="int" default="24">
The horizontal range within which a port can be grabbed (on both sides). The horizontal range within which a port can be grabbed (on both sides).
</theme_item> </theme_item>
<theme_item name="port_grab_distance_vertical" data_type="constant" type="int" default="6"> <theme_item name="port_grab_distance_vertical" data_type="constant" type="int" default="26">
The vertical range within which a port can be grabbed (on both sides). The vertical range within which a port can be grabbed (on both sides).
</theme_item> </theme_item>
<theme_item name="minimap" data_type="icon" type="Texture"> <theme_item name="minimap" data_type="icon" type="Texture">

View File

@ -93,7 +93,7 @@
<argument index="1" name="edge" type="int" /> <argument index="1" name="edge" type="int" />
<description> <description>
Returns specified edge associated with given face. Returns specified edge associated with given face.
Edge argument must 2 or less because a face only has three edges. Edge argument must be either 0, 1, or 2 because a face only has three edges.
</description> </description>
</method> </method>
<method name="get_face_meta" qualifiers="const"> <method name="get_face_meta" qualifiers="const">
@ -116,7 +116,7 @@
<argument index="1" name="vertex" type="int" /> <argument index="1" name="vertex" type="int" />
<description> <description>
Returns the specified vertex of the given face. Returns the specified vertex of the given face.
Vertex argument must be 2 or less because faces contain three vertices. Vertex argument must be either 0, 1, or 2 because faces contain three vertices.
</description> </description>
</method> </method>
<method name="get_format" qualifiers="const"> <method name="get_format" qualifiers="const">

View File

@ -17,7 +17,7 @@
</member> </member>
<member name="normal_map" type="Texture" setter="set_normal_map" getter="get_normal_map"> <member name="normal_map" type="Texture" setter="set_normal_map" getter="get_normal_map">
The normal map that will be used if using the default [CanvasItemMaterial]. The normal map that will be used if using the default [CanvasItemMaterial].
[b]Note:[/b] Godot expects the normal map to use X+, Y-, and Z+ coordinates. See [url=http://wiki.polycount.com/wiki/Normal_Map_Technical_Details#Common_Swizzle_Coordinates]this page[/url] for a comparison of normal map coordinates expected by popular engines. [b]Note:[/b] Godot expects the normal map to use X+, Y+, and Z+ coordinates. See [url=http://wiki.polycount.com/wiki/Normal_Map_Technical_Details#Common_Swizzle_Coordinates]this page[/url] for a comparison of normal map coordinates expected by popular engines.
</member> </member>
<member name="texture" type="Texture" setter="set_texture" getter="get_texture"> <member name="texture" type="Texture" setter="set_texture" getter="get_texture">
The [Texture] that will be used if using the default [CanvasItemMaterial]. Can be accessed as [code]TEXTURE[/code] in CanvasItem shader. The [Texture] that will be used if using the default [CanvasItemMaterial]. Can be accessed as [code]TEXTURE[/code] in CanvasItem shader.

View File

@ -17,7 +17,7 @@
</member> </member>
<member name="normal_map" type="Texture" setter="set_normal_map" getter="get_normal_map"> <member name="normal_map" type="Texture" setter="set_normal_map" getter="get_normal_map">
The normal map that will be used if using the default [CanvasItemMaterial]. The normal map that will be used if using the default [CanvasItemMaterial].
[b]Note:[/b] Godot expects the normal map to use X+, Y-, and Z+ coordinates. See [url=http://wiki.polycount.com/wiki/Normal_Map_Technical_Details#Common_Swizzle_Coordinates]this page[/url] for a comparison of normal map coordinates expected by popular engines. [b]Note:[/b] Godot expects the normal map to use X+, Y+, and Z+ coordinates. See [url=http://wiki.polycount.com/wiki/Normal_Map_Technical_Details#Common_Swizzle_Coordinates]this page[/url] for a comparison of normal map coordinates expected by popular engines.
</member> </member>
<member name="texture" type="Texture" setter="set_texture" getter="get_texture"> <member name="texture" type="Texture" setter="set_texture" getter="get_texture">
The [Texture] that will be used if using the default [CanvasItemMaterial]. Can be accessed as [code]TEXTURE[/code] in CanvasItem shader. The [Texture] that will be used if using the default [CanvasItemMaterial]. Can be accessed as [code]TEXTURE[/code] in CanvasItem shader.

View File

@ -163,6 +163,7 @@
[codeblock] [codeblock]
ProjectSettings.set_setting("application/config/name", "Example") ProjectSettings.set_setting("application/config/name", "Example")
[/codeblock] [/codeblock]
This can also be used to erase custom project settings. To do this change the setting value to [code]null[/code].
</description> </description>
</method> </method>
</methods> </methods>

View File

@ -122,7 +122,7 @@
The custom color to use to draw the shape in the editor and at run-time if [b]Visible Collision Shapes[/b] is enabled in the [b]Debug[/b] menu. This color will be highlighted at run-time if the [RayCast] is colliding with something. The custom color to use to draw the shape in the editor and at run-time if [b]Visible Collision Shapes[/b] is enabled in the [b]Debug[/b] menu. This color will be highlighted at run-time if the [RayCast] is colliding with something.
If set to [code]Color(0.0, 0.0, 0.0)[/code] (by default), the color set in [member ProjectSettings.debug/shapes/collision/shape_color] is used. If set to [code]Color(0.0, 0.0, 0.0)[/code] (by default), the color set in [member ProjectSettings.debug/shapes/collision/shape_color] is used.
</member> </member>
<member name="debug_shape_thickness" type="float" setter="set_debug_shape_thickness" getter="get_debug_shape_thickness" default="2.0"> <member name="debug_shape_thickness" type="int" setter="set_debug_shape_thickness" getter="get_debug_shape_thickness" default="2">
If set to [code]1[/code], a line is used as the debug shape. Otherwise, a truncated pyramid is drawn to represent the [RayCast]. Requires [b]Visible Collision Shapes[/b] to be enabled in the [b]Debug[/b] menu for the debug shape to be visible at run-time. If set to [code]1[/code], a line is used as the debug shape. Otherwise, a truncated pyramid is drawn to represent the [RayCast]. Requires [b]Visible Collision Shapes[/b] to be enabled in the [b]Debug[/b] menu for the debug shape to be visible at run-time.
</member> </member>
<member name="enabled" type="bool" setter="set_enabled" getter="is_enabled" default="false"> <member name="enabled" type="bool" setter="set_enabled" getter="is_enabled" default="false">

View File

@ -7,7 +7,6 @@
[Rect2] consists of a position, a size, and several utility functions. It is typically used for fast overlap tests. [Rect2] consists of a position, a size, and several utility functions. It is typically used for fast overlap tests.
It uses floating-point coordinates. It uses floating-point coordinates.
The 3D counterpart to [Rect2] is [AABB]. The 3D counterpart to [Rect2] is [AABB].
Negative values for [member size] are not supported and will not work for most methods. Use [method abs] to get a Rect2 with a positive size.
</description> </description>
<tutorials> <tutorials>
<link title="Math tutorial index">$DOCS_URL/tutorials/math/index.html</link> <link title="Math tutorial index">$DOCS_URL/tutorials/math/index.html</link>

View File

@ -27,6 +27,19 @@
If [code]true[/code], the slider will display ticks for minimum and maximum values. If [code]true[/code], the slider will display ticks for minimum and maximum values.
</member> </member>
</members> </members>
<signals>
<signal name="drag_ended">
<argument index="0" name="value_changed" type="bool" />
<description>
Emitted when dragging stops. If [code]value_changed[/code] is true, [member Range.value] is different from the value when you started the dragging.
</description>
</signal>
<signal name="drag_started">
<description>
Emitted when dragging is started.
</description>
</signal>
</signals>
<constants> <constants>
</constants> </constants>
</class> </class>

View File

@ -146,7 +146,7 @@
</member> </member>
<member name="detail_normal" type="Texture" setter="set_texture" getter="get_texture"> <member name="detail_normal" type="Texture" setter="set_texture" getter="get_texture">
Texture that specifies the per-pixel normal of the detail overlay. Texture that specifies the per-pixel normal of the detail overlay.
[b]Note:[/b] Godot expects the normal map to use X+, Y-, and Z+ coordinates. See [url=http://wiki.polycount.com/wiki/Normal_Map_Technical_Details#Common_Swizzle_Coordinates]this page[/url] for a comparison of normal map coordinates expected by popular engines. [b]Note:[/b] Godot expects the normal map to use X+, Y+, and Z+ coordinates. See [url=http://wiki.polycount.com/wiki/Normal_Map_Technical_Details#Common_Swizzle_Coordinates]this page[/url] for a comparison of normal map coordinates expected by popular engines.
</member> </member>
<member name="detail_uv_layer" type="int" setter="set_detail_uv" getter="get_detail_uv" enum="SpatialMaterial.DetailUV"> <member name="detail_uv_layer" type="int" setter="set_detail_uv" getter="get_detail_uv" enum="SpatialMaterial.DetailUV">
Specifies whether to use [code]UV[/code] or [code]UV2[/code] for the detail layer. See [enum DetailUV] for options. Specifies whether to use [code]UV[/code] or [code]UV2[/code] for the detail layer. See [enum DetailUV] for options.
@ -239,7 +239,7 @@
<member name="normal_texture" type="Texture" setter="set_texture" getter="get_texture"> <member name="normal_texture" type="Texture" setter="set_texture" getter="get_texture">
Texture used to specify the normal at a given pixel. The [code]normal_texture[/code] only uses the red and green channels; the blue and alpha channels are ignored. The normal read from [code]normal_texture[/code] is oriented around the surface normal provided by the [Mesh]. Texture used to specify the normal at a given pixel. The [code]normal_texture[/code] only uses the red and green channels; the blue and alpha channels are ignored. The normal read from [code]normal_texture[/code] is oriented around the surface normal provided by the [Mesh].
[b]Note:[/b] The mesh must have both normals and tangents defined in its vertex data. Otherwise, the normal map won't render correctly and will only appear to darken the whole surface. If creating geometry with [SurfaceTool], you can use [method SurfaceTool.generate_normals] and [method SurfaceTool.generate_tangents] to automatically generate normals and tangents respectively. [b]Note:[/b] The mesh must have both normals and tangents defined in its vertex data. Otherwise, the normal map won't render correctly and will only appear to darken the whole surface. If creating geometry with [SurfaceTool], you can use [method SurfaceTool.generate_normals] and [method SurfaceTool.generate_tangents] to automatically generate normals and tangents respectively.
[b]Note:[/b] Godot expects the normal map to use X+, Y-, and Z+ coordinates. See [url=http://wiki.polycount.com/wiki/Normal_Map_Technical_Details#Common_Swizzle_Coordinates]this page[/url] for a comparison of normal map coordinates expected by popular engines. [b]Note:[/b] Godot expects the normal map to use X+, Y+, and Z+ coordinates. See [url=http://wiki.polycount.com/wiki/Normal_Map_Technical_Details#Common_Swizzle_Coordinates]this page[/url] for a comparison of normal map coordinates expected by popular engines.
</member> </member>
<member name="params_alpha_scissor_threshold" type="float" setter="set_alpha_scissor_threshold" getter="get_alpha_scissor_threshold"> <member name="params_alpha_scissor_threshold" type="float" setter="set_alpha_scissor_threshold" getter="get_alpha_scissor_threshold">
Threshold at which the alpha scissor will discard values. Threshold at which the alpha scissor will discard values.

View File

@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<class name="SpriteFrames" inherits="Resource" version="3.5"> <class name="SpriteFrames" inherits="Resource" version="3.5">
<brief_description> <brief_description>
Sprite frame library for AnimatedSprite. Sprite frame library for AnimatedSprite and AnimatedSprite3D.
</brief_description> </brief_description>
<description> <description>
Sprite frame library for [AnimatedSprite]. Contains frames and animation data for playback. Sprite frame library for an [AnimatedSprite] or [AnimatedSprite3D] node. Contains frames and animation data for playback.
[b]Note:[/b] You can associate a set of normal maps by creating additional [SpriteFrames] resources with a [code]_normal[/code] suffix. For example, having 2 [SpriteFrames] resources [code]run[/code] and [code]run_normal[/code] will make it so the [code]run[/code] animation uses the normal map. [b]Note:[/b] You can associate a set of normal maps by creating additional [SpriteFrames] resources with a [code]_normal[/code] suffix. For example, having 2 [SpriteFrames] resources [code]run[/code] and [code]run_normal[/code] will make it so the [code]run[/code] animation uses the normal map.
</description> </description>
<tutorials> <tutorials>

View File

@ -86,7 +86,9 @@
<return type="float" /> <return type="float" />
<argument index="0" name="with" type="Vector2" /> <argument index="0" name="with" type="Vector2" />
<description> <description>
Returns the cross product of this vector and [code]with[/code]. Returns the 2D analog of the cross product for this vector and [code]with[/code].
This is the signed area of the parallelogram formed by the two vectors. If the second vector is clockwise from the first vector, then the cross product is the positive area. If counter-clockwise, the cross product is the negative area.
[b]Note:[/b] Cross product is not defined in 2D mathematically. This method embeds the 2D vectors in the XY plane of 3D space and uses their cross product's Z component as the analog.
</description> </description>
</method> </method>
<method name="cubic_interpolate"> <method name="cubic_interpolate">

View File

@ -2665,8 +2665,8 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
} }
} }
} break; } break;
case RUN_PROJECT_DATA_FOLDER: { case RUN_USER_DATA_FOLDER: {
// ensure_user_data_dir() to prevent the edge case: "Open Project Data Folder" won't work after the project was renamed in ProjectSettingsEditor unless the project is saved // ensure_user_data_dir() to prevent the edge case: "Open User Data Folder" won't work after the project was renamed in ProjectSettingsEditor unless the project is saved
OS::get_singleton()->ensure_user_data_dir(); OS::get_singleton()->ensure_user_data_dir();
OS::get_singleton()->shell_open(String("file://") + OS::get_singleton()->get_user_data_dir()); OS::get_singleton()->shell_open(String("file://") + OS::get_singleton()->get_user_data_dir());
} break; } break;
@ -6333,7 +6333,7 @@ EditorNode::EditorNode() {
p->add_separator(); p->add_separator();
p->add_shortcut(ED_SHORTCUT("editor/export", TTR("Export...")), FILE_EXPORT_PROJECT); p->add_shortcut(ED_SHORTCUT("editor/export", TTR("Export...")), FILE_EXPORT_PROJECT);
p->add_item(TTR("Install Android Build Template..."), FILE_INSTALL_ANDROID_SOURCE); p->add_item(TTR("Install Android Build Template..."), FILE_INSTALL_ANDROID_SOURCE);
p->add_item(TTR("Open Project Data Folder"), RUN_PROJECT_DATA_FOLDER); p->add_item(TTR("Open User Data Folder"), RUN_USER_DATA_FOLDER);
plugin_config_dialog = memnew(PluginConfigDialog); plugin_config_dialog = memnew(PluginConfigDialog);
plugin_config_dialog->connect("plugin_ready", this, "_on_plugin_ready"); plugin_config_dialog->connect("plugin_ready", this, "_on_plugin_ready");

View File

@ -163,7 +163,7 @@ private:
RUN_PLAY_CUSTOM_SCENE, RUN_PLAY_CUSTOM_SCENE,
RUN_SCENE_SETTINGS, RUN_SCENE_SETTINGS,
RUN_SETTINGS, RUN_SETTINGS,
RUN_PROJECT_DATA_FOLDER, RUN_USER_DATA_FOLDER,
RUN_RELOAD_CURRENT_PROJECT, RUN_RELOAD_CURRENT_PROJECT,
RUN_PROJECT_MANAGER, RUN_PROJECT_MANAGER,
RUN_FILE_SERVER, RUN_FILE_SERVER,

View File

@ -775,7 +775,8 @@ InputDefault::InputDefault() {
void InputDefault::joy_button(int p_device, int p_button, bool p_pressed) { void InputDefault::joy_button(int p_device, int p_button, bool p_pressed) {
_THREAD_SAFE_METHOD_; _THREAD_SAFE_METHOD_;
Joypad &joy = joy_names[p_device]; Joypad &joy = joy_names[p_device];
//printf("got button %i, mapping is %i\n", p_button, joy.mapping); ERR_FAIL_INDEX(p_button, JOY_BUTTON_MAX);
if (joy.last_buttons[p_button] == p_pressed) { if (joy.last_buttons[p_button] == p_pressed) {
return; return;
} }

View File

@ -1104,7 +1104,7 @@ HashMap<int, R> FBXMeshData::extract_per_vertex_data(
const int vertex_index = get_vertex_from_polygon_vertex(p_mesh_indices, polygon_vertex_index); const int vertex_index = get_vertex_from_polygon_vertex(p_mesh_indices, polygon_vertex_index);
ERR_FAIL_COND_V_MSG(vertex_index < 0, (HashMap<int, R>()), "FBX file corrupted: #ERR05"); ERR_FAIL_COND_V_MSG(vertex_index < 0, (HashMap<int, R>()), "FBX file corrupted: #ERR05");
ERR_FAIL_COND_V_MSG(vertex_index >= p_vertex_count, (HashMap<int, R>()), "FBX file corrupted: #ERR06"); ERR_FAIL_COND_V_MSG(vertex_index >= p_vertex_count, (HashMap<int, R>()), "FBX file corrupted: #ERR06");
const int index_to_direct = p_mapping_data.index[polygon_vertex_index]; const int index_to_direct = get_vertex_from_polygon_vertex(p_mapping_data.index, polygon_vertex_index);
T value = p_mapping_data.data[index_to_direct]; T value = p_mapping_data.data[index_to_direct];
aggregate_vertex_data[vertex_index].push_back({ polygon_id, value }); aggregate_vertex_data[vertex_index].push_back({ polygon_id, value });
} }
@ -1309,7 +1309,7 @@ HashMap<int, T> FBXMeshData::extract_per_polygon(
} else { } else {
ERR_FAIL_INDEX_V_MSG(polygon_index, (int)p_fbx_data.index.size(), (HashMap<int, T>()), "FBX file is corrupted: #ERR62"); ERR_FAIL_INDEX_V_MSG(polygon_index, (int)p_fbx_data.index.size(), (HashMap<int, T>()), "FBX file is corrupted: #ERR62");
const int index_to_direct = p_fbx_data.index[polygon_index]; const int index_to_direct = get_vertex_from_polygon_vertex(p_fbx_data.index, polygon_index);
T value = p_fbx_data.data[index_to_direct]; T value = p_fbx_data.data[index_to_direct];
aggregate_polygon_data[polygon_index].push_back(value); aggregate_polygon_data[polygon_index].push_back(value);
} }

View File

@ -6586,103 +6586,110 @@ Error GLTFDocument::parse(Ref<GLTFState> state, String p_path, bool p_read_binar
state->major_version = version.get_slice(".", 0).to_int(); state->major_version = version.get_slice(".", 0).to_int();
state->minor_version = version.get_slice(".", 1).to_int(); state->minor_version = version.get_slice(".", 1).to_int();
/* STEP 0 PARSE SCENE */ /* PARSE EXTENSIONS */
err = _parse_gltf_extensions(state);
if (err != OK) {
return Error::FAILED;
}
/* PARSE SCENE */
err = _parse_scenes(state); err = _parse_scenes(state);
if (err != OK) { if (err != OK) {
return Error::FAILED; return Error::FAILED;
} }
/* STEP 1 PARSE NODES */ /* PARSE NODES */
err = _parse_nodes(state); err = _parse_nodes(state);
if (err != OK) { if (err != OK) {
return Error::FAILED; return Error::FAILED;
} }
/* STEP 2 PARSE BUFFERS */ /* PARSE BUFFERS */
err = _parse_buffers(state, p_path.get_base_dir()); err = _parse_buffers(state, p_path.get_base_dir());
if (err != OK) { if (err != OK) {
return Error::FAILED; return Error::FAILED;
} }
/* STEP 3 PARSE BUFFER VIEWS */ /* PARSE BUFFER VIEWS */
err = _parse_buffer_views(state); err = _parse_buffer_views(state);
if (err != OK) { if (err != OK) {
return Error::FAILED; return Error::FAILED;
} }
/* STEP 4 PARSE ACCESSORS */ /* PARSE ACCESSORS */
err = _parse_accessors(state); err = _parse_accessors(state);
if (err != OK) { if (err != OK) {
return Error::FAILED; return Error::FAILED;
} }
/* STEP 5 PARSE IMAGES */ /* PARSE IMAGES */
err = _parse_images(state, p_path.get_base_dir()); err = _parse_images(state, p_path.get_base_dir());
if (err != OK) { if (err != OK) {
return Error::FAILED; return Error::FAILED;
} }
/* STEP 6 PARSE TEXTURES */ /* PARSE TEXTURES */
err = _parse_textures(state); err = _parse_textures(state);
if (err != OK) { if (err != OK) {
return Error::FAILED; return Error::FAILED;
} }
/* STEP 7 PARSE TEXTURES */ /* PARSE TEXTURES */
err = _parse_materials(state); err = _parse_materials(state);
if (err != OK) { if (err != OK) {
return Error::FAILED; return Error::FAILED;
} }
/* STEP 9 PARSE SKINS */ /* PARSE SKINS */
err = _parse_skins(state); err = _parse_skins(state);
if (err != OK) { if (err != OK) {
return Error::FAILED; return Error::FAILED;
} }
/* STEP 10 DETERMINE SKELETONS */ /* DETERMINE SKELETONS */
err = _determine_skeletons(state); err = _determine_skeletons(state);
if (err != OK) { if (err != OK) {
return Error::FAILED; return Error::FAILED;
} }
/* STEP 11 CREATE SKELETONS */ /* CREATE SKELETONS */
err = _create_skeletons(state); err = _create_skeletons(state);
if (err != OK) { if (err != OK) {
return Error::FAILED; return Error::FAILED;
} }
/* STEP 12 CREATE SKINS */ /* CREATE SKINS */
err = _create_skins(state); err = _create_skins(state);
if (err != OK) { if (err != OK) {
return Error::FAILED; return Error::FAILED;
} }
/* STEP 13 PARSE MESHES (we have enough info now) */ /* PARSE MESHES (we have enough info now) */
err = _parse_meshes(state); err = _parse_meshes(state);
if (err != OK) { if (err != OK) {
return Error::FAILED; return Error::FAILED;
} }
/* STEP 14 PARSE LIGHTS */ /* PARSE LIGHTS */
err = _parse_lights(state); err = _parse_lights(state);
if (err != OK) { if (err != OK) {
return Error::FAILED; return Error::FAILED;
} }
/* STEP 15 PARSE CAMERAS */ /* PARSE CAMERAS */
err = _parse_cameras(state); err = _parse_cameras(state);
if (err != OK) { if (err != OK) {
return Error::FAILED; return Error::FAILED;
} }
/* STEP 16 PARSE ANIMATIONS */ /* PARSE ANIMATIONS */
err = _parse_animations(state); err = _parse_animations(state);
if (err != OK) { if (err != OK) {
return Error::FAILED; return Error::FAILED;
} }
/* STEP 17 ASSIGN SCENE NAMES */ /* ASSIGN SCENE NAMES */
_assign_scene_names(state); _assign_scene_names(state);
return OK; return OK;
@ -6802,3 +6809,15 @@ Error GLTFDocument::_serialize_file(Ref<GLTFState> state, const String p_path) {
} }
return err; return err;
} }
Error GLTFDocument::_parse_gltf_extensions(Ref<GLTFState> state) {
ERR_FAIL_COND_V(!state.is_valid(), ERR_PARSE_ERROR);
if (state->json.has("extensionsRequired") && state->json["extensionsRequired"].get_type() == Variant::ARRAY) {
Array extensions_required = state->json["extensionsRequired"];
if (extensions_required.find("KHR_draco_mesh_compression") != -1) {
ERR_PRINT("glTF2 extension KHR_draco_mesh_compression is not supported.");
return ERR_UNAVAILABLE;
}
}
return OK;
}

View File

@ -373,6 +373,8 @@ public:
String _sanitize_scene_name(Ref<GLTFState> state, const String &p_name); String _sanitize_scene_name(Ref<GLTFState> state, const String &p_name);
String _legacy_validate_node_name(const String &p_name); String _legacy_validate_node_name(const String &p_name);
Error _parse_gltf_extensions(Ref<GLTFState> state);
void _process_mesh_instances(Ref<GLTFState> state, Node *scene_root); void _process_mesh_instances(Ref<GLTFState> state, Node *scene_root);
void _generate_scene_node(Ref<GLTFState> state, Node *scene_parent, void _generate_scene_node(Ref<GLTFState> state, Node *scene_parent,
Spatial *scene_root, Spatial *scene_root,

View File

@ -67,7 +67,7 @@ void WebSocketServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_handshake_timeout"), &WebSocketServer::get_handshake_timeout); ClassDB::bind_method(D_METHOD("get_handshake_timeout"), &WebSocketServer::get_handshake_timeout);
ClassDB::bind_method(D_METHOD("set_handshake_timeout", "timeout"), &WebSocketServer::set_handshake_timeout); ClassDB::bind_method(D_METHOD("set_handshake_timeout", "timeout"), &WebSocketServer::set_handshake_timeout);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "handshake_timeout"), "set_handshake_timeout", "get_handshake_timeout"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "handshake_timeout"), "set_handshake_timeout", "get_handshake_timeout");
ADD_SIGNAL(MethodInfo("client_close_request", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::INT, "code"), PropertyInfo(Variant::STRING, "reason"))); ADD_SIGNAL(MethodInfo("client_close_request", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::INT, "code"), PropertyInfo(Variant::STRING, "reason")));
ADD_SIGNAL(MethodInfo("client_disconnected", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::BOOL, "was_clean_close"))); ADD_SIGNAL(MethodInfo("client_disconnected", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::BOOL, "was_clean_close")));

View File

@ -170,9 +170,9 @@ static NSCursor *cursorFromSelector(SEL selector, SEL fallback = nil) {
@implementation GodotApplicationDelegate @implementation GodotApplicationDelegate
- (void)forceUnbundledWindowActivationHackStep1 { - (void)forceUnbundledWindowActivationHackStep1 {
// Step1: Switch focus to macOS Dock. // Step 1: Switch focus to macOS SystemUIServer process.
// Required to perform step 2, TransformProcessType will fail if app is already the in focus. // Required to perform step 2, TransformProcessType will fail if app is already the in focus.
for (NSRunningApplication *app in [NSRunningApplication runningApplicationsWithBundleIdentifier:@"com.apple.dock"]) { for (NSRunningApplication *app in [NSRunningApplication runningApplicationsWithBundleIdentifier:@"com.apple.systemuiserver"]) {
[app activateWithOptions:NSApplicationActivateIgnoringOtherApps]; [app activateWithOptions:NSApplicationActivateIgnoringOtherApps];
break; break;
} }
@ -194,8 +194,8 @@ static NSCursor *cursorFromSelector(SEL selector, SEL fallback = nil) {
- (void)applicationDidFinishLaunching:(NSNotification *)notice { - (void)applicationDidFinishLaunching:(NSNotification *)notice {
NSString *nsappname = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"]; NSString *nsappname = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"];
if (nsappname == nil) { if (nsappname == nil || isatty(STDOUT_FILENO) || isatty(STDIN_FILENO) || isatty(STDERR_FILENO)) {
// If executable is not a bundled, macOS WindowServer won't register and activate app window correctly (menu and title bar are grayed out and input ignored). // If the executable is started from terminal or is not bundled, macOS WindowServer won't register and activate app window correctly (menu and title bar are grayed out and input ignored).
[self performSelector:@selector(forceUnbundledWindowActivationHackStep1) withObject:nil afterDelay:0.02]; [self performSelector:@selector(forceUnbundledWindowActivationHackStep1) withObject:nil afterDelay:0.02];
} }
} }

View File

@ -137,12 +137,8 @@ void OS_UWP::initialize_core() {
NetSocketPosix::make_default(); NetSocketPosix::make_default();
// We need to know how often the clock is updated // We need to know how often the clock is updated
if (!QueryPerformanceFrequency((LARGE_INTEGER *)&ticks_per_second)) QueryPerformanceFrequency((LARGE_INTEGER *)&ticks_per_second);
ticks_per_second = 1000; QueryPerformanceCounter((LARGE_INTEGER *)&ticks_start);
// If timeAtGameStart is 0 then we get the time since
// the start of the computer when we call GetGameTime()
ticks_start = 0;
ticks_start = get_ticks_usec();
IP_Unix::make_default(); IP_Unix::make_default();
@ -564,6 +560,9 @@ uint64_t OS_UWP::get_ticks_usec() const {
// This is the number of clock ticks since start // This is the number of clock ticks since start
QueryPerformanceCounter((LARGE_INTEGER *)&ticks); QueryPerformanceCounter((LARGE_INTEGER *)&ticks);
// Subtract the ticks at game start to get
// the ticks since the game started
ticks -= ticks_start;
// Divide by frequency to get the time in seconds // Divide by frequency to get the time in seconds
// original calculation shown below is subject to overflow // original calculation shown below is subject to overflow
@ -583,9 +582,6 @@ uint64_t OS_UWP::get_ticks_usec() const {
// seconds // seconds
time += seconds * 1000000L; time += seconds * 1000000L;
// Subtract the time at game start to get
// the time since the game started
time -= ticks_start;
return time; return time;
} }

View File

@ -174,12 +174,8 @@ void OS_Windows::initialize_core() {
NetSocketPosix::make_default(); NetSocketPosix::make_default();
// We need to know how often the clock is updated // We need to know how often the clock is updated
if (!QueryPerformanceFrequency((LARGE_INTEGER *)&ticks_per_second)) QueryPerformanceFrequency((LARGE_INTEGER *)&ticks_per_second);
ticks_per_second = 1000; QueryPerformanceCounter((LARGE_INTEGER *)&ticks_start);
// If timeAtGameStart is 0 then we get the time since
// the start of the computer when we call GetGameTime()
ticks_start = 0;
ticks_start = get_ticks_usec();
// set minimum resolution for periodic timers, otherwise Sleep(n) may wait at least as // set minimum resolution for periodic timers, otherwise Sleep(n) may wait at least as
// long as the windows scheduler resolution (~16-30ms) even for calls like Sleep(1) // long as the windows scheduler resolution (~16-30ms) even for calls like Sleep(1)
@ -2460,8 +2456,10 @@ uint64_t OS_Windows::get_ticks_usec() const {
uint64_t ticks; uint64_t ticks;
// This is the number of clock ticks since start // This is the number of clock ticks since start
if (!QueryPerformanceCounter((LARGE_INTEGER *)&ticks)) QueryPerformanceCounter((LARGE_INTEGER *)&ticks);
ticks = (UINT64)timeGetTime(); // Subtract the ticks at game start to get
// the ticks since the game started
ticks -= ticks_start;
// Divide by frequency to get the time in seconds // Divide by frequency to get the time in seconds
// original calculation shown below is subject to overflow // original calculation shown below is subject to overflow
@ -2481,9 +2479,6 @@ uint64_t OS_Windows::get_ticks_usec() const {
// seconds // seconds
time += seconds * 1000000L; time += seconds * 1000000L;
// Subtract the time at game start to get
// the time since the game started
time -= ticks_start;
return time; return time;
} }

View File

@ -94,6 +94,10 @@ void Path2D::_notification(int p_what) {
return; return;
} }
if (curve->get_point_count() < 2) {
return;
}
#ifdef TOOLS_ENABLED #ifdef TOOLS_ENABLED
const float line_width = 2 * EDSCALE; const float line_width = 2 * EDSCALE;
#else #else

View File

@ -636,7 +636,7 @@ void Polygon2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR2_ARRAY, "uv"), "set_uv", "get_uv"); ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR2_ARRAY, "uv"), "set_uv", "get_uv");
ADD_PROPERTY(PropertyInfo(Variant::POOL_COLOR_ARRAY, "vertex_colors"), "set_vertex_colors", "get_vertex_colors"); ADD_PROPERTY(PropertyInfo(Variant::POOL_COLOR_ARRAY, "vertex_colors"), "set_vertex_colors", "get_vertex_colors");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "polygons"), "set_polygons", "get_polygons"); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "polygons"), "set_polygons", "get_polygons");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "bones", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_bones", "_get_bones"); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "bones", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_bones", "_get_bones");
ADD_PROPERTY(PropertyInfo(Variant::INT, "internal_vertex_count", PROPERTY_HINT_RANGE, "0,1000"), "set_internal_vertex_count", "get_internal_vertex_count"); ADD_PROPERTY(PropertyInfo(Variant::INT, "internal_vertex_count", PROPERTY_HINT_RANGE, "0,1000"), "set_internal_vertex_count", "get_internal_vertex_count");
} }

View File

@ -332,7 +332,7 @@ void RayCast::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "debug_shape_thickness", PROPERTY_HINT_RANGE, "1,5"), "set_debug_shape_thickness", "get_debug_shape_thickness"); ADD_PROPERTY(PropertyInfo(Variant::INT, "debug_shape_thickness", PROPERTY_HINT_RANGE, "1,5"), "set_debug_shape_thickness", "get_debug_shape_thickness");
} }
float RayCast::get_debug_shape_thickness() const { int RayCast::get_debug_shape_thickness() const {
return debug_shape_thickness; return debug_shape_thickness;
} }
@ -361,7 +361,7 @@ void RayCast::_update_debug_shape_vertices() {
} }
} }
void RayCast::set_debug_shape_thickness(const float p_debug_shape_thickness) { void RayCast::set_debug_shape_thickness(const int p_debug_shape_thickness) {
debug_shape_thickness = p_debug_shape_thickness; debug_shape_thickness = p_debug_shape_thickness;
update_gizmo(); update_gizmo();

View File

@ -100,8 +100,8 @@ public:
Ref<SpatialMaterial> get_debug_material(); Ref<SpatialMaterial> get_debug_material();
float get_debug_shape_thickness() const; int get_debug_shape_thickness() const;
void set_debug_shape_thickness(const float p_debug_thickness); void set_debug_shape_thickness(const int p_debug_thickness);
void force_raycast_update(); void force_raycast_update();
bool is_colliding() const; bool is_colliding() const;

View File

@ -567,6 +567,7 @@ void FileDialog::clear_filters() {
invalidate(); invalidate();
} }
void FileDialog::add_filter(const String &p_filter) { void FileDialog::add_filter(const String &p_filter) {
ERR_FAIL_COND_MSG(p_filter.begins_with("."), "Filter must be \"filename.extension\", can't start with dot.");
filters.push_back(p_filter); filters.push_back(p_filter);
update_filters(); update_filters();
invalidate(); invalidate();

View File

@ -1667,6 +1667,7 @@ void RichTextLabel::_remove_item(Item *p_item, const int p_line, const int p_sub
_remove_item(p_item->subitems.front()->get(), p_line, p_subitem_line); _remove_item(p_item->subitems.front()->get(), p_line, p_subitem_line);
} }
} }
memdelete(p_item);
} }
void RichTextLabel::add_image(const Ref<Texture> &p_image, const int p_width, const int p_height) { void RichTextLabel::add_image(const Ref<Texture> &p_image, const int p_width, const int p_height) {
@ -2164,6 +2165,12 @@ Error RichTextLabel::append_bbcode(const String &p_bbcode) {
push_strikethrough(); push_strikethrough();
pos = brk_end + 1; pos = brk_end + 1;
tag_stack.push_front(tag); tag_stack.push_front(tag);
} else if (tag == "lb") {
add_text("[");
pos = brk_end + 1;
} else if (tag == "rb") {
add_text("]");
pos = brk_end + 1;
} else if (tag == "center") { } else if (tag == "center") {
push_align(ALIGN_CENTER); push_align(ALIGN_CENTER);
pos = brk_end + 1; pos = brk_end + 1;

View File

@ -68,8 +68,13 @@ void Slider::_gui_input(Ref<InputEvent> p_event) {
} }
grab.active = true; grab.active = true;
grab.uvalue = get_as_ratio(); grab.uvalue = get_as_ratio();
emit_signal("drag_started");
} else { } else {
grab.active = false; grab.active = false;
const bool value_changed = !Math::is_equal_approx((double)grab.uvalue, get_as_ratio());
emit_signal("drag_ended", value_changed);
} }
} else if (scrollable) { } else if (scrollable) {
if (mb->is_pressed() && mb->get_button_index() == BUTTON_WHEEL_UP) { if (mb->is_pressed() && mb->get_button_index() == BUTTON_WHEEL_UP) {
@ -263,6 +268,9 @@ void Slider::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_scrollable", "scrollable"), &Slider::set_scrollable); ClassDB::bind_method(D_METHOD("set_scrollable", "scrollable"), &Slider::set_scrollable);
ClassDB::bind_method(D_METHOD("is_scrollable"), &Slider::is_scrollable); ClassDB::bind_method(D_METHOD("is_scrollable"), &Slider::is_scrollable);
ADD_SIGNAL(MethodInfo("drag_started"));
ADD_SIGNAL(MethodInfo("drag_ended", PropertyInfo(Variant::BOOL, "value_changed")));
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editable"), "set_editable", "is_editable"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editable"), "set_editable", "is_editable");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scrollable"), "set_scrollable", "is_scrollable"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scrollable"), "set_scrollable", "is_scrollable");
ADD_PROPERTY(PropertyInfo(Variant::INT, "tick_count", PROPERTY_HINT_RANGE, "0,4096,1"), "set_ticks", "get_ticks"); ADD_PROPERTY(PropertyInfo(Variant::INT, "tick_count", PROPERTY_HINT_RANGE, "0,4096,1"), "set_ticks", "get_ticks");

View File

@ -382,6 +382,7 @@ void TextEdit::_update_scrollbars() {
cursor.line_ofs = 0; cursor.line_ofs = 0;
cursor.wrap_ofs = 0; cursor.wrap_ofs = 0;
v_scroll->set_value(0); v_scroll->set_value(0);
v_scroll->set_max(0);
v_scroll->hide(); v_scroll->hide();
} }
@ -399,6 +400,7 @@ void TextEdit::_update_scrollbars() {
} else { } else {
cursor.x_ofs = 0; cursor.x_ofs = 0;
h_scroll->set_value(0); h_scroll->set_value(0);
h_scroll->set_max(0);
h_scroll->hide(); h_scroll->hide();
} }

View File

@ -168,6 +168,12 @@ void TextureButton::_notification(int p_what) {
Point2 ofs; Point2 ofs;
Size2 size; Size2 size;
bool draw_focus = (has_focus() && focused.is_valid());
// If no other texture is valid, try using focused texture.
if (!texdraw.is_valid() && draw_focus) {
texdraw = focused;
}
if (texdraw.is_valid()) { if (texdraw.is_valid()) {
size = texdraw->get_size(); size = texdraw->get_size();
@ -224,7 +230,9 @@ void TextureButton::_notification(int p_what) {
size.width *= hflip ? -1.0f : 1.0f; size.width *= hflip ? -1.0f : 1.0f;
size.height *= vflip ? -1.0f : 1.0f; size.height *= vflip ? -1.0f : 1.0f;
if (_tile) { if (texdraw == focused) {
// Do nothing, we only needed to calculate the rectangle.
} else if (_tile) {
draw_texture_rect(texdraw, Rect2(ofs, size), _tile); draw_texture_rect(texdraw, Rect2(ofs, size), _tile);
} else { } else {
draw_texture_rect_region(texdraw, Rect2(ofs, size), _texture_region); draw_texture_rect_region(texdraw, Rect2(ofs, size), _texture_region);
@ -233,7 +241,7 @@ void TextureButton::_notification(int p_what) {
_position_rect = Rect2(); _position_rect = Rect2();
} }
if (has_focus() && focused.is_valid()) { if (draw_focus) {
draw_texture_rect(focused, Rect2(ofs, size), false); draw_texture_rect(focused, Rect2(ofs, size), false);
}; };
} break; } break;

View File

@ -109,10 +109,37 @@ Variant PropertyUtils::get_property_default_value(const Object *p_object, const
} }
// Fall back to the default from the native class // Fall back to the default from the native class
{
if (r_is_class_default) { if (r_is_class_default) {
*r_is_class_default = true; *r_is_class_default = true;
} }
return ClassDB::class_get_default_property_value(p_object->get_class_name(), p_property, r_is_valid); bool valid = false;
Variant value = ClassDB::class_get_default_property_value(p_object->get_class_name(), p_property, &valid);
if (valid) {
if (r_is_valid) {
*r_is_valid = true;
}
return value;
} else {
// Heuristically check if this is a synthetic property (whatever/0, whatever/1, etc.)
// because they are not in the class DB yet must have a default (null).
String prop_str = String(p_property);
int p = prop_str.rfind("/");
if (p != -1 && p < prop_str.length() - 1) {
bool all_digits = true;
for (int i = p + 1; i < prop_str.length(); i++) {
if (prop_str[i] < '0' || prop_str[i] > '9') {
all_digits = false;
break;
}
}
if (r_is_valid) {
*r_is_valid = all_digits;
}
}
return Variant();
}
}
} }
// Like SceneState::PackState, but using a raw pointer to avoid the cost of // Like SceneState::PackState, but using a raw pointer to avoid the cost of

View File

@ -903,7 +903,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
// Visual Node Ports // Visual Node Ports
theme->set_constant("port_grab_distance_horizontal", "GraphEdit", 24 * scale); theme->set_constant("port_grab_distance_horizontal", "GraphEdit", 24 * scale);
theme->set_constant("port_grab_distance_vertical", "GraphEdit", 6 * scale); theme->set_constant("port_grab_distance_vertical", "GraphEdit", 26 * scale);
theme->set_stylebox("bg", "GraphEditMinimap", make_flat_stylebox(Color(0.24, 0.24, 0.24), 0, 0, 0, 0)); theme->set_stylebox("bg", "GraphEditMinimap", make_flat_stylebox(Color(0.24, 0.24, 0.24), 0, 0, 0, 0));
Ref<StyleBoxFlat> style_minimap_camera = make_flat_stylebox(Color(0.65, 0.65, 0.65, 0.2), 0, 0, 0, 0); Ref<StyleBoxFlat> style_minimap_camera = make_flat_stylebox(Color(0.65, 0.65, 0.65, 0.2), 0, 0, 0, 0);