summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/class_db.cpp1
-rw-r--r--core/global_config.cpp74
-rw-r--r--core/global_config.h3
-rw-r--r--core/io/resource_loader.cpp2
-rw-r--r--core/math/math_2d.cpp9
-rw-r--r--core/math/math_defs.h4
-rw-r--r--core/math/math_funcs.cpp6
-rw-r--r--core/math/math_funcs.h4
-rw-r--r--core/math/matrix3.cpp126
-rw-r--r--core/math/matrix3.h20
-rw-r--r--core/math/quat.cpp4
-rw-r--r--core/math/quat.h3
-rw-r--r--core/math/vector3.h7
-rw-r--r--core/os/os.cpp1
-rw-r--r--core/script_language.h4
-rw-r--r--core/typedefs.h11
-rw-r--r--core/variant_call.cpp18
-rw-r--r--core/version.h37
18 files changed, 258 insertions, 76 deletions
diff --git a/core/class_db.cpp b/core/class_db.cpp
index 94a907a1f0..0ca982303d 100644
--- a/core/class_db.cpp
+++ b/core/class_db.cpp
@@ -30,6 +30,7 @@
#include "class_db.h"
#include "os/mutex.h"
+#include "version.h"
#ifdef NO_THREADS
diff --git a/core/global_config.cpp b/core/global_config.cpp
index d37c67c84a..f9a0877c23 100644
--- a/core/global_config.cpp
+++ b/core/global_config.cpp
@@ -53,6 +53,11 @@ String GlobalConfig::get_resource_path() const {
return resource_path;
};
+String GlobalConfig::get_project_file_name() const {
+
+ return project_file_name;
+}
+
String GlobalConfig::localize_path(const String &p_path) const {
if (resource_path == "")
@@ -236,13 +241,43 @@ bool GlobalConfig::_load_resource_pack(const String &p_pack) {
return true;
}
+static String _find_project_file(DirAccess *p_diraccess, bool p_res = false) {
+ p_diraccess->list_dir_begin();
+ String ret = "";
+ while (true) {
+ bool isdir;
+ String file = p_diraccess->get_next(&isdir);
+ if (file == "")
+ break;
+
+ if (!isdir) {
+ if (file.get_extension() == "godot") {
+
+ if (p_res) {
+ ret = "res://" + file;
+ } else {
+ ret = p_diraccess->get_current_dir() + "/" + file;
+ }
+ }
+ }
+ }
+ p_diraccess->list_dir_end();
+ return ret;
+}
+
+static String _find_project_file() {
+ DirAccess *dir = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ String ret = _find_project_file(dir, true);
+ memdelete(dir);
+ return ret;
+}
+
Error GlobalConfig::setup(const String &p_path, const String &p_main_pack) {
//If looking for files in network, just use network!
-
if (FileAccessNetworkClient::get_singleton()) {
-
- if (_load_settings("res://godot.cfg") == OK || _load_settings_binary("res://godot.cfb") == OK) {
+ String gdproj = _find_project_file();
+ if (_load_settings(gdproj) == OK || _load_settings_binary("res://godot.cfb") == OK) {
_load_settings("res://override.cfg");
}
@@ -258,8 +293,8 @@ Error GlobalConfig::setup(const String &p_path, const String &p_main_pack) {
bool ok = _load_resource_pack(p_main_pack);
ERR_FAIL_COND_V(!ok, ERR_CANT_OPEN);
-
- if (_load_settings("res://godot.cfg") == OK || _load_settings_binary("res://godot.cfb") == OK) {
+ String gdproj = _find_project_file();
+ if (_load_settings(gdproj) == OK || _load_settings_binary("res://godot.cfb") == OK) {
//load override from location of the main pack
_load_settings(p_main_pack.get_base_dir().plus_file("override.cfg"));
}
@@ -272,7 +307,8 @@ Error GlobalConfig::setup(const String &p_path, const String &p_main_pack) {
if (_load_resource_pack(exec_path.get_basename() + ".pck")) {
- if (_load_settings("res://godot.cfg") == OK || _load_settings_binary("res://godot.cfb") == OK) {
+ String gdproj = _find_project_file();
+ if (_load_settings(gdproj) == OK || _load_settings_binary("res://godot.cfb") == OK) {
//load override from location of executable
_load_settings(exec_path.get_base_dir().plus_file("override.cfg"));
}
@@ -292,15 +328,15 @@ Error GlobalConfig::setup(const String &p_path, const String &p_main_pack) {
// data.pck and data.zip are deprecated and no longer supported, apologies.
// make sure this is loaded from the resource path
-
- if (_load_settings("res://godot.cfg") == OK || _load_settings_binary("res://godot.cfb") == OK) {
+ String gdproj = _find_project_file();
+ if (_load_settings(gdproj) == OK || _load_settings_binary("res://godot.cfb") == OK) {
_load_settings("res://override.cfg");
}
return OK;
}
- //Nothing was found, try to find a godot.cfg somewhere!
+ //Nothing was found, try to find a *.godot somewhere!
DirAccess *d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
ERR_FAIL_COND_V(!d, ERR_CANT_CREATE);
@@ -313,8 +349,8 @@ Error GlobalConfig::setup(const String &p_path, const String &p_main_pack) {
while (true) {
//try to load settings in ascending through dirs shape!
-
- if (_load_settings(current_dir + "/godot.cfg") == OK || _load_settings_binary(current_dir + "/godot.cfb") == OK) {
+ String gdproj = _find_project_file(d);
+ if (_load_settings(gdproj) == OK || _load_settings_binary(current_dir + "/godot.cfb") == OK) {
_load_settings(current_dir + "/override.cfg");
candidate = current_dir;
@@ -428,6 +464,7 @@ Error GlobalConfig::_load_settings(const String p_path) {
err = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, NULL, true);
if (err == ERR_FILE_EOF) {
memdelete(f);
+ project_file_name = p_path.get_file();
return OK;
} else if (err != OK) {
ERR_PRINTS("GlobalConfig::load - " + p_path + ":" + itos(lines) + " error: " + error_text);
@@ -449,6 +486,7 @@ Error GlobalConfig::_load_settings(const String p_path) {
}
}
+ project_file_name = p_path.get_file();
memdelete(f);
return OK;
@@ -474,7 +512,12 @@ void GlobalConfig::clear(const String &p_name) {
Error GlobalConfig::save() {
- return save_custom(get_resource_path() + "/godot.cfg");
+ if (project_file_name.empty()) {
+ String name = ((String)get("application/name")).replace(" ", "_");
+ return save_custom(get_resource_path() + "/" + name + ".godot");
+ } else {
+ return save_custom(get_resource_path() + "/" + project_file_name);
+ }
}
Error GlobalConfig::_save_settings_binary(const String &p_file, const Map<String, List<String> > &props, const CustomMap &p_custom) {
@@ -483,7 +526,7 @@ Error GlobalConfig::_save_settings_binary(const String &p_file, const Map<String
FileAccess *file = FileAccess::open(p_file, FileAccess::WRITE, &err);
if (err != OK) {
- ERR_EXPLAIN("Coudln't save godot.cfb at " + p_file);
+ ERR_EXPLAIN("Couldn't save godot.cfb at " + p_file);
ERR_FAIL_COND_V(err, err)
}
@@ -548,7 +591,7 @@ Error GlobalConfig::_save_settings_text(const String &p_file, const Map<String,
FileAccess *file = FileAccess::open(p_file, FileAccess::WRITE, &err);
if (err) {
- ERR_EXPLAIN("Coudln't save godot.cfg - " + p_file);
+ ERR_EXPLAIN("Couldn't save project file - " + p_file);
ERR_FAIL_COND_V(err, err)
}
@@ -658,7 +701,7 @@ Error GlobalConfig::save_custom(const String &p_path, const CustomMap &p_custom,
props[category].push_back(name);
}
- if (p_path.ends_with(".cfg"))
+ if (p_path.ends_with(".godot"))
return _save_settings_text(p_path, props, p_custom);
else if (p_path.ends_with(".cfb"))
return _save_settings_binary(p_path, props, p_custom);
@@ -828,6 +871,7 @@ void GlobalConfig::_bind_methods() {
ClassDB::bind_method(D_METHOD("clear", "name"), &GlobalConfig::clear);
ClassDB::bind_method(D_METHOD("localize_path", "path"), &GlobalConfig::localize_path);
ClassDB::bind_method(D_METHOD("globalize_path", "path"), &GlobalConfig::globalize_path);
+ ClassDB::bind_method(D_METHOD("get_project_file_name"), &GlobalConfig::get_project_file_name);
ClassDB::bind_method(D_METHOD("save"), &GlobalConfig::save);
ClassDB::bind_method(D_METHOD("has_singleton", "name"), &GlobalConfig::has_singleton);
ClassDB::bind_method(D_METHOD("get_singleton", "name"), &GlobalConfig::get_singleton_object);
diff --git a/core/global_config.h b/core/global_config.h
index d0f64dc23c..5148c4377e 100644
--- a/core/global_config.h
+++ b/core/global_config.h
@@ -111,6 +111,8 @@ protected:
void _add_property_info_bind(const Dictionary &p_info);
+ String project_file_name;
+
protected:
static void _bind_methods();
@@ -124,6 +126,7 @@ public:
Variant property_get_revert(const String &p_name);
String get_resource_path() const;
+ String get_project_file_name() const;
static GlobalConfig *get_singleton();
diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp
index 3b43492bc5..234d71cb68 100644
--- a/core/io/resource_loader.cpp
+++ b/core/io/resource_loader.cpp
@@ -179,10 +179,10 @@ RES ResourceLoader::load(const String &p_path, const String &p_type_hint, bool p
print_line("load resource: " + local_path);
bool found = false;
+ // Try all loaders and pick the first match for the type hint
for (int i = 0; i < loader_count; i++) {
if (!loader[i]->recognize_path(local_path, p_type_hint)) {
- print_line("path not recognized");
continue;
}
found = true;
diff --git a/core/math/math_2d.cpp b/core/math/math_2d.cpp
index 20b916ee3b..962a42acb9 100644
--- a/core/math/math_2d.cpp
+++ b/core/math/math_2d.cpp
@@ -63,7 +63,8 @@ Vector2 Vector2::normalized() const {
}
bool Vector2::is_normalized() const {
- return Math::isequal_approx(length(), (real_t)1.0);
+ // use length_squared() instead of length() to avoid sqrt(), makes it more stringent.
+ return Math::is_equal_approx(length_squared(), 1.0);
}
real_t Vector2::distance_to(const Vector2 &p_vector2) const {
@@ -281,7 +282,7 @@ Vector2 Vector2::cubic_interpolate(const Vector2 &p_b, const Vector2 &p_pre_a, c
// slide returns the component of the vector along the given plane, specified by its normal vector.
Vector2 Vector2::slide(const Vector2 &p_n) const {
-#ifdef DEBUG_ENABLED
+#ifdef MATH_CHECKS
ERR_FAIL_COND_V(p_n.is_normalized() == false, Vector2());
#endif
return *this - p_n * this->dot(p_n);
@@ -292,7 +293,7 @@ Vector2 Vector2::bounce(const Vector2 &p_n) const {
}
Vector2 Vector2::reflect(const Vector2 &p_n) const {
-#ifdef DEBUG_ENABLED
+#ifdef MATH_CHECKS
ERR_FAIL_COND_V(p_n.is_normalized() == false, Vector2());
#endif
return 2.0 * p_n * this->dot(p_n) - *this;
@@ -439,7 +440,9 @@ Transform2D Transform2D::inverse() const {
void Transform2D::affine_invert() {
real_t det = basis_determinant();
+#ifdef MATH_CHECKS
ERR_FAIL_COND(det == 0);
+#endif
real_t idet = 1.0 / det;
SWAP(elements[0][0], elements[1][1]);
diff --git a/core/math/math_defs.h b/core/math/math_defs.h
index 1a5768e515..3d9eb63e11 100644
--- a/core/math/math_defs.h
+++ b/core/math/math_defs.h
@@ -35,6 +35,10 @@
#define CMP_NORMALIZE_TOLERANCE 0.000001
#define CMP_POINT_IN_PLANE_EPSILON 0.00001
+#ifdef DEBUG_ENABLED
+#define MATH_CHECKS
+#endif
+
#define USEC_TO_SEC(m_usec) ((m_usec) / 1000000.0)
/**
* "Real" is a type that will be translated to either floats or fixed depending
diff --git a/core/math/math_funcs.cpp b/core/math/math_funcs.cpp
index 6a46b9fbe3..9f5a9c193a 100644
--- a/core/math/math_funcs.cpp
+++ b/core/math/math_funcs.cpp
@@ -30,7 +30,7 @@
#include "math_funcs.h"
#include "core/os/os.h"
-pcg32_random_t Math::default_pcg = { 1, PCG_DEFAULT_INC_64 };
+pcg32_random_t Math::default_pcg = { 12047754176567800795ULL, PCG_DEFAULT_INC_64 };
#define PHI 0x9e3779b9
@@ -51,9 +51,7 @@ void Math::seed(uint64_t x) {
}
void Math::randomize() {
-
- OS::Time time = OS::get_singleton()->get_time();
- seed(OS::get_singleton()->get_ticks_usec() * (time.hour + 1) * (time.min + 1) * (time.sec + 1) * rand()); // TODO: can be simplified.
+ seed(OS::get_singleton()->get_ticks_usec() * default_pcg.state + PCG_DEFAULT_INC_64);
}
uint32_t Math::rand() {
diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h
index 10426c9243..5bfbc1005f 100644
--- a/core/math/math_funcs.h
+++ b/core/math/math_funcs.h
@@ -157,7 +157,7 @@ public:
static uint32_t larger_prime(uint32_t p_val);
- static void seed(uint64_t x = 0);
+ static void seed(uint64_t x);
static void randomize();
static uint32_t rand_from_seed(uint64_t *seed);
static uint32_t rand();
@@ -168,7 +168,7 @@ public:
static float random(float from, float to);
static real_t random(int from, int to) { return (real_t)random((real_t)from, (real_t)to); }
- static _ALWAYS_INLINE_ bool isequal_approx(real_t a, real_t b) {
+ static _ALWAYS_INLINE_ bool is_equal_approx(real_t a, real_t b) {
// TODO: Comparing floats for approximate-equality is non-trivial.
// Using epsilon should cover the typical cases in Godot (where a == b is used to compare two reals), such as matrix and vector comparison operators.
// A proper implementation in terms of ULPs should eventually replace the contents of this function.
diff --git a/core/math/matrix3.cpp b/core/math/matrix3.cpp
index ef368009d1..c733251c3c 100644
--- a/core/math/matrix3.cpp
+++ b/core/math/matrix3.cpp
@@ -62,8 +62,9 @@ void Basis::invert() {
real_t det = elements[0][0] * co[0] +
elements[0][1] * co[1] +
elements[0][2] * co[2];
-
+#ifdef MATH_CHECKS
ERR_FAIL_COND(det == 0);
+#endif
real_t s = 1.0 / det;
set(co[0] * s, cofac(0, 2, 2, 1) * s, cofac(0, 1, 1, 2) * s,
@@ -72,8 +73,9 @@ void Basis::invert() {
}
void Basis::orthonormalize() {
+#ifdef MATH_CHECKS
ERR_FAIL_COND(determinant() == 0);
-
+#endif
// Gram-Schmidt Process
Vector3 x = get_axis(0);
@@ -102,20 +104,20 @@ bool Basis::is_orthogonal() const {
Basis id;
Basis m = (*this) * transposed();
- return isequal_approx(id, m);
+ return is_equal_approx(id, m);
}
bool Basis::is_rotation() const {
- return Math::isequal_approx(determinant(), 1) && is_orthogonal();
+ return Math::is_equal_approx(determinant(), 1) && is_orthogonal();
}
bool Basis::is_symmetric() const {
- if (Math::abs(elements[0][1] - elements[1][0]) > CMP_EPSILON)
+ if (!Math::is_equal_approx(elements[0][1], elements[1][0]))
return false;
- if (Math::abs(elements[0][2] - elements[2][0]) > CMP_EPSILON)
+ if (!Math::is_equal_approx(elements[0][2], elements[2][0]))
return false;
- if (Math::abs(elements[1][2] - elements[2][1]) > CMP_EPSILON)
+ if (!Math::is_equal_approx(elements[1][2], elements[2][1]))
return false;
return true;
@@ -123,11 +125,11 @@ bool Basis::is_symmetric() const {
Basis Basis::diagonalize() {
- //NOTE: only implemented for symmetric matrices
- //with the Jacobi iterative method method
-
+//NOTE: only implemented for symmetric matrices
+//with the Jacobi iterative method method
+#ifdef MATH_CHECKS
ERR_FAIL_COND_V(!is_symmetric(), Basis());
-
+#endif
const int ite_max = 1024;
real_t off_matrix_norm_2 = elements[0][1] * elements[0][1] + elements[0][2] * elements[0][2] + elements[1][2] * elements[1][2];
@@ -160,7 +162,7 @@ Basis Basis::diagonalize() {
// Compute the rotation angle
real_t angle;
- if (Math::abs(elements[j][j] - elements[i][i]) < CMP_EPSILON) {
+ if (Math::is_equal_approx(elements[j][j], elements[i][i])) {
angle = Math_PI / 4;
} else {
angle = 0.5 * Math::atan(2 * elements[i][j] / (elements[j][j] - elements[i][i]));
@@ -226,11 +228,25 @@ Basis Basis::scaled(const Vector3 &p_scale) const {
}
Vector3 Basis::get_scale() const {
- // We are assuming M = R.S, and performing a polar decomposition to extract R and S.
- // FIXME: We eventually need a proper polar decomposition.
- // As a cheap workaround until then, to ensure that R is a proper rotation matrix with determinant +1
- // (such that it can be represented by a Quat or Euler angles), we absorb the sign flip into the scaling matrix.
- // As such, it works in conjunction with get_rotation().
+ // FIXME: We are assuming M = R.S (R is rotation and S is scaling), and use polar decomposition to extract R and S.
+ // A polar decomposition is M = O.P, where O is an orthogonal matrix (meaning rotation and reflection) and
+ // P is a positive semi-definite matrix (meaning it contains absolute values of scaling along its diagonal).
+ //
+ // Despite being different from what we want to achieve, we can nevertheless make use of polar decomposition
+ // here as follows. We can split O into a rotation and a reflection as O = R.Q, and obtain M = R.S where
+ // we defined S = Q.P. Now, R is a proper rotation matrix and S is a (signed) scaling matrix,
+ // which can involve negative scalings. However, there is a catch: unlike the polar decomposition of M = O.P,
+ // the decomposition of O into a rotation and reflection matrix as O = R.Q is not unique.
+ // Therefore, we are going to do this decomposition by sticking to a particular convention.
+ // This may lead to confusion for some users though.
+ //
+ // The convention we use here is to absorb the sign flip into the scaling matrix.
+ // The same convention is also used in other similar functions such as set_scale,
+ // get_rotation_axis_angle, get_rotation, set_rotation_axis_angle, set_rotation_euler, ...
+ //
+ // A proper way to get rid of this issue would be to store the scaling values (or at least their signs)
+ // as a part of Basis. However, if we go that path, we need to disable direct (write) access to the
+ // matrix elements.
real_t det_sign = determinant() > 0 ? 1 : -1;
return det_sign * Vector3(
Vector3(elements[0][0], elements[1][0], elements[2][0]).length(),
@@ -238,6 +254,17 @@ Vector3 Basis::get_scale() const {
Vector3(elements[0][2], elements[1][2], elements[2][2]).length());
}
+// Sets scaling while preserving rotation.
+// This requires some care when working with matrices with negative determinant,
+// since we're using a particular convention for "polar" decomposition in get_scale and get_rotation.
+// For details, see the explanation in get_scale.
+void Basis::set_scale(const Vector3 &p_scale) {
+ Vector3 e = get_euler();
+ Basis(); // reset to identity
+ scale(p_scale);
+ rotate(e);
+}
+
// Multiplies the matrix from left by the rotation matrix: M -> R.M
// Note that this does *not* rotate the matrix itself.
//
@@ -260,6 +287,7 @@ void Basis::rotate(const Vector3 &p_euler) {
*this = rotated(p_euler);
}
+// TODO: rename this to get_rotation_euler
Vector3 Basis::get_rotation() const {
// Assumes that the matrix can be decomposed into a proper rotation and scaling matrix as M = R.S,
// and returns the Euler angles corresponding to the rotation part, complementing get_scale().
@@ -274,6 +302,42 @@ Vector3 Basis::get_rotation() const {
return m.get_euler();
}
+void Basis::get_rotation_axis_angle(Vector3 &p_axis, real_t &p_angle) const {
+ // Assumes that the matrix can be decomposed into a proper rotation and scaling matrix as M = R.S,
+ // and returns the Euler angles corresponding to the rotation part, complementing get_scale().
+ // See the comment in get_scale() for further information.
+ Basis m = orthonormalized();
+ real_t det = m.determinant();
+ if (det < 0) {
+ // Ensure that the determinant is 1, such that result is a proper rotation matrix which can be represented by Euler angles.
+ m.scale(Vector3(-1, -1, -1));
+ }
+
+ m.get_axis_angle(p_axis, p_angle);
+}
+
+// Sets rotation while preserving scaling.
+// This requires some care when working with matrices with negative determinant,
+// since we're using a particular convention for "polar" decomposition in get_scale and get_rotation.
+// For details, see the explanation in get_scale.
+void Basis::set_rotation_euler(const Vector3 &p_euler) {
+ Vector3 s = get_scale();
+ Basis(); // reset to identity
+ scale(s);
+ rotate(p_euler);
+}
+
+// Sets rotation while preserving scaling.
+// This requires some care when working with matrices with negative determinant,
+// since we're using a particular convention for "polar" decomposition in get_scale and get_rotation.
+// For details, see the explanation in get_scale.
+void Basis::set_rotation_axis_angle(const Vector3 &p_axis, real_t p_angle) {
+ Vector3 s = get_scale();
+ Basis(); // reset to identity
+ scale(s);
+ rotate(p_axis, p_angle);
+}
+
// get_euler returns a vector containing the Euler angles in the format
// (a1,a2,a3), where a3 is the angle of the first rotation, and a1 is the last
// (following the convention they are commonly defined in the literature).
@@ -294,9 +358,9 @@ Vector3 Basis::get_euler() const {
// -cx*cz*sy+sx*sz cz*sx+cx*sy*sz cx*cy
Vector3 euler;
-
+#ifdef MATH_CHECKS
ERR_FAIL_COND_V(is_rotation() == false, euler);
-
+#endif
euler.y = Math::asin(elements[0][2]);
if (euler.y < Math_PI * 0.5) {
if (euler.y > -Math_PI * 0.5) {
@@ -340,11 +404,11 @@ void Basis::set_euler(const Vector3 &p_euler) {
*this = xmat * (ymat * zmat);
}
-bool Basis::isequal_approx(const Basis &a, const Basis &b) const {
+bool Basis::is_equal_approx(const Basis &a, const Basis &b) const {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
- if (Math::isequal_approx(a.elements[i][j], b.elements[i][j]) == false)
+ if (Math::is_equal_approx(a.elements[i][j], b.elements[i][j]) == false)
return false;
}
}
@@ -387,8 +451,9 @@ Basis::operator String() const {
}
Basis::operator Quat() const {
+#ifdef MATH_CHECKS
ERR_FAIL_COND_V(is_rotation() == false, Quat());
-
+#endif
real_t trace = elements[0][0] + elements[1][1] + elements[2][2];
real_t temp[4];
@@ -482,9 +547,10 @@ void Basis::set_orthogonal_index(int p_index) {
*this = _ortho_bases[p_index];
}
-void Basis::get_axis_and_angle(Vector3 &r_axis, real_t &r_angle) const {
+void Basis::get_axis_angle(Vector3 &r_axis, real_t &r_angle) const {
+#ifdef MATH_CHECKS
ERR_FAIL_COND(is_rotation() == false);
-
+#endif
real_t angle, x, y, z; // variables for result
real_t epsilon = 0.01; // margin to allow for rounding errors
real_t epsilon2 = 0.1; // margin to distinguish between 0 and 180 degrees
@@ -573,11 +639,11 @@ Basis::Basis(const Quat &p_quat) {
xz - wy, yz + wx, 1.0 - (xx + yy));
}
-Basis::Basis(const Vector3 &p_axis, real_t p_phi) {
- // Rotation matrix from axis and angle, see https://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle
-
+void Basis::set_axis_angle(const Vector3 &p_axis, real_t p_phi) {
+// Rotation matrix from axis and angle, see https://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_angle
+#ifdef MATH_CHECKS
ERR_FAIL_COND(p_axis.is_normalized() == false);
-
+#endif
Vector3 axis_sq(p_axis.x * p_axis.x, p_axis.y * p_axis.y, p_axis.z * p_axis.z);
real_t cosine = Math::cos(p_phi);
@@ -595,3 +661,7 @@ Basis::Basis(const Vector3 &p_axis, real_t p_phi) {
elements[2][1] = p_axis.y * p_axis.z * (1.0 - cosine) + p_axis.x * sine;
elements[2][2] = axis_sq.z + cosine * (1.0 - axis_sq.z);
}
+
+Basis::Basis(const Vector3 &p_axis, real_t p_phi) {
+ set_axis_angle(p_axis, p_phi);
+}
diff --git a/core/math/matrix3.h b/core/math/matrix3.h
index 08e963f56e..c3eeb1f705 100644
--- a/core/math/matrix3.h
+++ b/core/math/matrix3.h
@@ -77,15 +77,25 @@ public:
void rotate(const Vector3 &p_euler);
Basis rotated(const Vector3 &p_euler) const;
+
Vector3 get_rotation() const;
+ void get_rotation_axis_angle(Vector3 &p_axis, real_t &p_angle) const;
- void scale(const Vector3 &p_scale);
- Basis scaled(const Vector3 &p_scale) const;
- Vector3 get_scale() const;
+ void set_rotation_euler(const Vector3 &p_euler);
+ void set_rotation_axis_angle(const Vector3 &p_axis, real_t p_angle);
Vector3 get_euler() const;
void set_euler(const Vector3 &p_euler);
+ void get_axis_angle(Vector3 &r_axis, real_t &r_angle) const;
+ void set_axis_angle(const Vector3 &p_axis, real_t p_phi);
+
+ void scale(const Vector3 &p_scale);
+ Basis scaled(const Vector3 &p_scale) const;
+
+ Vector3 get_scale() const;
+ void set_scale(const Vector3 &p_scale);
+
// transposed dot products
_FORCE_INLINE_ real_t tdotx(const Vector3 &v) const {
return elements[0][0] * v[0] + elements[1][0] * v[1] + elements[2][0] * v[2];
@@ -97,7 +107,7 @@ public:
return elements[0][2] * v[0] + elements[1][2] * v[1] + elements[2][2] * v[2];
}
- bool isequal_approx(const Basis &a, const Basis &b) const;
+ bool is_equal_approx(const Basis &a, const Basis &b) const;
bool operator==(const Basis &p_matrix) const;
bool operator!=(const Basis &p_matrix) const;
@@ -121,8 +131,6 @@ public:
operator String() const;
- void get_axis_and_angle(Vector3 &r_axis, real_t &r_angle) const;
-
/* create / set */
_FORCE_INLINE_ void set(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) {
diff --git a/core/math/quat.cpp b/core/math/quat.cpp
index 9662542224..0bea97c2e8 100644
--- a/core/math/quat.cpp
+++ b/core/math/quat.cpp
@@ -92,6 +92,10 @@ Quat Quat::normalized() const {
return *this / length();
}
+bool Quat::is_normalized() const {
+ return Math::is_equal_approx(length(), 1.0);
+}
+
Quat Quat::inverse() const {
return Quat(-x, -y, -z, w);
}
diff --git a/core/math/quat.h b/core/math/quat.h
index 76b3cde2a3..f22275b457 100644
--- a/core/math/quat.h
+++ b/core/math/quat.h
@@ -48,6 +48,7 @@ public:
real_t length() const;
void normalize();
Quat normalized() const;
+ bool is_normalized() const;
Quat inverse() const;
_FORCE_INLINE_ real_t dot(const Quat &q) const;
void set_euler(const Vector3 &p_euler);
@@ -56,7 +57,7 @@ public:
Quat slerpni(const Quat &q, const real_t &t) const;
Quat cubic_slerp(const Quat &q, const Quat &prep, const Quat &postq, const real_t &t) const;
- _FORCE_INLINE_ void get_axis_and_angle(Vector3 &r_axis, real_t &r_angle) const {
+ _FORCE_INLINE_ void get_axis_angle(Vector3 &r_axis, real_t &r_angle) const {
r_angle = 2 * Math::acos(w);
r_axis.x = x / Math::sqrt(1 - w * w);
r_axis.y = y / Math::sqrt(1 - w * w);
diff --git a/core/math/vector3.h b/core/math/vector3.h
index a6bc20ccb2..5f4390fbd1 100644
--- a/core/math/vector3.h
+++ b/core/math/vector3.h
@@ -389,7 +389,8 @@ Vector3 Vector3::normalized() const {
}
bool Vector3::is_normalized() const {
- return Math::isequal_approx(length(), (real_t)1.0);
+ // use length_squared() instead of length() to avoid sqrt(), makes it more stringent.
+ return Math::is_equal_approx(length_squared(), 1.0);
}
Vector3 Vector3::inverse() const {
@@ -404,7 +405,7 @@ void Vector3::zero() {
// slide returns the component of the vector along the given plane, specified by its normal vector.
Vector3 Vector3::slide(const Vector3 &p_n) const {
-#ifdef DEBUG_ENABLED
+#ifdef MATH_CHECKS
ERR_FAIL_COND_V(p_n.is_normalized() == false, Vector3());
#endif
return *this - p_n * this->dot(p_n);
@@ -415,7 +416,7 @@ Vector3 Vector3::bounce(const Vector3 &p_n) const {
}
Vector3 Vector3::reflect(const Vector3 &p_n) const {
-#ifdef DEBUG_ENABLED
+#ifdef MATH_CHECKS
ERR_FAIL_COND_V(p_n.is_normalized() == false, Vector3());
#endif
return 2.0 * p_n * this->dot(p_n) - *this;
diff --git a/core/os/os.cpp b/core/os/os.cpp
index ab03bb8016..e323e03829 100644
--- a/core/os/os.cpp
+++ b/core/os/os.cpp
@@ -507,7 +507,6 @@ OS::OS() {
_render_thread_mode = RENDER_THREAD_SAFE;
_allow_hidpi = true;
- Math::seed(1234567);
}
OS::~OS() {
diff --git a/core/script_language.h b/core/script_language.h
index 905ac4eeda..115ab59dca 100644
--- a/core/script_language.h
+++ b/core/script_language.h
@@ -119,7 +119,7 @@ public:
virtual void get_script_method_list(List<MethodInfo> *p_list) const = 0;
virtual void get_script_property_list(List<PropertyInfo> *p_list) const = 0;
- virtual int get_member_line(const StringName &p_member) const { return 0; }
+ virtual int get_member_line(const StringName &p_member) const { return -1; }
Script() {}
};
@@ -199,8 +199,10 @@ public:
virtual bool validate(const String &p_script, int &r_line_error, int &r_col_error, String &r_test_error, const String &p_path = "", List<String> *r_functions = NULL) const = 0;
virtual Script *create_script() const = 0;
virtual bool has_named_classes() const = 0;
+ virtual bool can_inherit_from_file() { return false; }
virtual int find_function(const String &p_function, const String &p_code) const = 0;
virtual String make_function(const String &p_class, const String &p_name, const PoolStringArray &p_args) const = 0;
+ virtual Error open_in_external_editor(const Ref<Script> &p_script, int p_line, int p_col) { return ERR_UNAVAILABLE; }
virtual Error complete_code(const String &p_code, const String &p_base_path, Object *p_owner, List<String> *r_options, String &r_call_hint) { return ERR_UNAVAILABLE; }
diff --git a/core/typedefs.h b/core/typedefs.h
index 335f576bce..40d9ea37b5 100644
--- a/core/typedefs.h
+++ b/core/typedefs.h
@@ -42,17 +42,6 @@
#define _MKSTR(m_x) _STR(m_x)
#endif
-/**
- * Version macros - it is necessary to include "version.h" for those to work.
- * Include it in the .cpp file, not the header.
- */
-#ifdef VERSION_PATCH
-#define VERSION_MKSTRING "" _MKSTR(VERSION_MAJOR) "." _MKSTR(VERSION_MINOR) "." _MKSTR(VERSION_PATCH) "." _MKSTR(VERSION_STATUS) "." _MKSTR(VERSION_REVISION)
-#else
-#define VERSION_MKSTRING "" _MKSTR(VERSION_MAJOR) "." _MKSTR(VERSION_MINOR) "." _MKSTR(VERSION_STATUS) "." _MKSTR(VERSION_REVISION)
-#endif // VERSION_PATCH
-#define VERSION_FULL_NAME "" _MKSTR(VERSION_NAME) " v" VERSION_MKSTRING
-
#ifndef _ALWAYS_INLINE_
#if defined(__GNUC__) && (__GNUC__ >= 4)
diff --git a/core/variant_call.cpp b/core/variant_call.cpp
index e87dfd2768..beaee188eb 100644
--- a/core/variant_call.cpp
+++ b/core/variant_call.cpp
@@ -328,6 +328,7 @@ struct _VariantCall {
VCALL_LOCALMEM0R(Vector2, normalized);
VCALL_LOCALMEM0R(Vector2, length);
VCALL_LOCALMEM0R(Vector2, length_squared);
+ VCALL_LOCALMEM0R(Vector2, is_normalized);
VCALL_LOCALMEM1R(Vector2, distance_to);
VCALL_LOCALMEM1R(Vector2, distance_squared_to);
VCALL_LOCALMEM1R(Vector2, angle_to);
@@ -362,6 +363,7 @@ struct _VariantCall {
VCALL_LOCALMEM0R(Vector3, max_axis);
VCALL_LOCALMEM0R(Vector3, length);
VCALL_LOCALMEM0R(Vector3, length_squared);
+ VCALL_LOCALMEM0R(Vector3, is_normalized);
VCALL_LOCALMEM0R(Vector3, normalized);
VCALL_LOCALMEM0R(Vector3, inverse);
VCALL_LOCALMEM1R(Vector3, snapped);
@@ -418,6 +420,7 @@ struct _VariantCall {
VCALL_LOCALMEM0R(Quat, length);
VCALL_LOCALMEM0R(Quat, length_squared);
VCALL_LOCALMEM0R(Quat, normalized);
+ VCALL_LOCALMEM0R(Quat, is_normalized);
VCALL_LOCALMEM0R(Quat, inverse);
VCALL_LOCALMEM1R(Quat, dot);
VCALL_LOCALMEM1R(Quat, xform);
@@ -704,6 +707,9 @@ struct _VariantCall {
VCALL_PTR1R(Basis, scaled);
VCALL_PTR0R(Basis, get_scale);
VCALL_PTR0R(Basis, get_euler);
+ VCALL_PTR1(Basis, set_scale);
+ VCALL_PTR1(Basis, set_rotation_euler);
+ VCALL_PTR2(Basis, set_rotation_axis_angle);
VCALL_PTR1R(Basis, tdotx);
VCALL_PTR1R(Basis, tdoty);
VCALL_PTR1R(Basis, tdotz);
@@ -875,6 +881,11 @@ struct _VariantCall {
r_ret = Basis(p_args[0]->operator Vector3(), p_args[1]->operator real_t());
}
+ static void Basis_init3(Variant &r_ret, const Variant **p_args) {
+
+ r_ret = Basis(p_args[0]->operator Vector3());
+ }
+
static void Transform_init1(Variant &r_ret, const Variant **p_args) {
Transform t;
@@ -1429,6 +1440,7 @@ void register_variant_methods() {
ADDFUNC0(VECTOR2, REAL, Vector2, length, varray());
ADDFUNC0(VECTOR2, REAL, Vector2, angle, varray());
ADDFUNC0(VECTOR2, REAL, Vector2, length_squared, varray());
+ ADDFUNC0(VECTOR2, BOOL, Vector2, is_normalized, varray());
ADDFUNC1(VECTOR2, REAL, Vector2, distance_to, VECTOR2, "to", varray());
ADDFUNC1(VECTOR2, REAL, Vector2, distance_squared_to, VECTOR2, "to", varray());
ADDFUNC1(VECTOR2, REAL, Vector2, angle_to, VECTOR2, "to", varray());
@@ -1462,6 +1474,7 @@ void register_variant_methods() {
ADDFUNC0(VECTOR3, INT, Vector3, max_axis, varray());
ADDFUNC0(VECTOR3, REAL, Vector3, length, varray());
ADDFUNC0(VECTOR3, REAL, Vector3, length_squared, varray());
+ ADDFUNC0(VECTOR3, BOOL, Vector3, is_normalized, varray());
ADDFUNC0(VECTOR3, VECTOR3, Vector3, normalized, varray());
ADDFUNC0(VECTOR3, VECTOR3, Vector3, inverse, varray());
ADDFUNC1(VECTOR3, VECTOR3, Vector3, snapped, REAL, "by", varray());
@@ -1497,6 +1510,7 @@ void register_variant_methods() {
ADDFUNC0(QUAT, REAL, Quat, length, varray());
ADDFUNC0(QUAT, REAL, Quat, length_squared, varray());
ADDFUNC0(QUAT, QUAT, Quat, normalized, varray());
+ ADDFUNC0(QUAT, BOOL, Quat, is_normalized, varray());
ADDFUNC0(QUAT, QUAT, Quat, inverse, varray());
ADDFUNC1(QUAT, REAL, Quat, dot, QUAT, "b", varray());
ADDFUNC1(QUAT, VECTOR3, Quat, xform, VECTOR3, "v", varray());
@@ -1692,6 +1706,9 @@ void register_variant_methods() {
ADDFUNC0(BASIS, REAL, Basis, determinant, varray());
ADDFUNC2(BASIS, BASIS, Basis, rotated, VECTOR3, "axis", REAL, "phi", varray());
ADDFUNC1(BASIS, BASIS, Basis, scaled, VECTOR3, "scale", varray());
+ ADDFUNC1(BASIS, NIL, Basis, set_scale, VECTOR3, "scale", varray());
+ ADDFUNC1(BASIS, NIL, Basis, set_rotation_euler, VECTOR3, "euler", varray());
+ ADDFUNC2(BASIS, NIL, Basis, set_rotation_axis_angle, VECTOR3, "axis", REAL, "angle", varray());
ADDFUNC0(BASIS, VECTOR3, Basis, get_scale, varray());
ADDFUNC0(BASIS, VECTOR3, Basis, get_euler, varray());
ADDFUNC1(BASIS, REAL, Basis, tdotx, VECTOR3, "with", varray());
@@ -1749,6 +1766,7 @@ void register_variant_methods() {
_VariantCall::add_constructor(_VariantCall::Basis_init1, Variant::BASIS, "x_axis", Variant::VECTOR3, "y_axis", Variant::VECTOR3, "z_axis", Variant::VECTOR3);
_VariantCall::add_constructor(_VariantCall::Basis_init2, Variant::BASIS, "axis", Variant::VECTOR3, "phi", Variant::REAL);
+ _VariantCall::add_constructor(_VariantCall::Basis_init3, Variant::BASIS, "euler", Variant::VECTOR3);
_VariantCall::add_constructor(_VariantCall::Transform_init1, Variant::TRANSFORM, "x_axis", Variant::VECTOR3, "y_axis", Variant::VECTOR3, "z_axis", Variant::VECTOR3, "origin", Variant::VECTOR3);
_VariantCall::add_constructor(_VariantCall::Transform_init2, Variant::TRANSFORM, "basis", Variant::BASIS, "origin", Variant::VECTOR3);
diff --git a/core/version.h b/core/version.h
new file mode 100644
index 0000000000..80e50e51b9
--- /dev/null
+++ b/core/version.h
@@ -0,0 +1,37 @@
+/*************************************************************************/
+/* version.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 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 "version_generated.h"
+
+#ifdef VERSION_PATCH
+#define VERSION_MKSTRING "" _MKSTR(VERSION_MAJOR) "." _MKSTR(VERSION_MINOR) "." _MKSTR(VERSION_PATCH) "." _MKSTR(VERSION_STATUS) "." _MKSTR(VERSION_REVISION)
+#else
+#define VERSION_MKSTRING "" _MKSTR(VERSION_MAJOR) "." _MKSTR(VERSION_MINOR) "." _MKSTR(VERSION_STATUS) "." _MKSTR(VERSION_REVISION)
+#endif // VERSION_PATCH
+#define VERSION_FULL_NAME "" _MKSTR(VERSION_NAME) " v" VERSION_MKSTRING