summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/cvtt/image_compress_cvtt.cpp4
-rw-r--r--modules/gdscript/gdscript_compiler.cpp19
-rw-r--r--modules/gdscript/gdscript_function.cpp16
-rw-r--r--modules/gdscript/gdscript_function.h1
-rw-r--r--modules/gdscript/gdscript_parser.cpp46
-rw-r--r--modules/gdscript/gdscript_parser.h1
-rw-r--r--modules/mono/glue/cs_files/Basis.cs2
-rw-r--r--modules/mono/glue/cs_files/Quat.cs97
-rw-r--r--modules/squish/image_compress_squish.cpp4
9 files changed, 152 insertions, 38 deletions
diff --git a/modules/cvtt/image_compress_cvtt.cpp b/modules/cvtt/image_compress_cvtt.cpp
index 3a371c8597..af92861352 100644
--- a/modules/cvtt/image_compress_cvtt.cpp
+++ b/modules/cvtt/image_compress_cvtt.cpp
@@ -247,8 +247,8 @@ void image_compress_cvtt(Image *p_image, float p_lossy_quality, Image::CompressS
}
dst_ofs += (MAX(4, bw) * MAX(4, bh)) >> shift;
- w >>= 1;
- h >>= 1;
+ w = MAX(w / 2, 1);
+ h = MAX(h / 2, 1);
}
if (num_job_threads > 0) {
diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp
index 3b494dbae7..006fbece53 100644
--- a/modules/gdscript/gdscript_compiler.cpp
+++ b/modules/gdscript/gdscript_compiler.cpp
@@ -1253,6 +1253,25 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser::
codegen.opcodes.push_back(src_address_b); // argument 2 (unary only takes one parameter)
} break;
+ case GDScriptParser::OperatorNode::OP_IS_BUILTIN: {
+ ERR_FAIL_COND_V(on->arguments.size() != 2, false);
+ ERR_FAIL_COND_V(on->arguments[1]->type != GDScriptParser::Node::TYPE_TYPE, false);
+
+ int slevel = p_stack_level;
+
+ int src_address_a = _parse_expression(codegen, on->arguments[0], slevel);
+ if (src_address_a < 0)
+ return -1;
+
+ if (src_address_a & GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS)
+ slevel++; //uses stack for return, increase stack
+
+ const GDScriptParser::TypeNode *tn = static_cast<const GDScriptParser::TypeNode *>(on->arguments[1]);
+
+ codegen.opcodes.push_back(GDScriptFunction::OPCODE_IS_BUILTIN); // perform operator
+ codegen.opcodes.push_back(src_address_a); // argument 1
+ codegen.opcodes.push_back((int)tn->vtype); // argument 2 (unary only takes one parameter)
+ } break;
default: {
ERR_EXPLAIN("Bug in bytecode compiler, unexpected operator #" + itos(on->op) + " in parse tree while parsing expression.");
diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp
index bae3f48923..d615b58b24 100644
--- a/modules/gdscript/gdscript_function.cpp
+++ b/modules/gdscript/gdscript_function.cpp
@@ -191,6 +191,7 @@ static String _get_var_type(const Variant *p_type) {
static const void *switch_table_ops[] = { \
&&OPCODE_OPERATOR, \
&&OPCODE_EXTENDS_TEST, \
+ &&OPCODE_IS_BUILTIN, \
&&OPCODE_SET, \
&&OPCODE_GET, \
&&OPCODE_SET_NAMED, \
@@ -536,6 +537,21 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
}
DISPATCH_OPCODE;
+ OPCODE(OPCODE_IS_BUILTIN) {
+
+ CHECK_SPACE(4);
+
+ GET_VARIANT_PTR(value, 1);
+ Variant::Type var_type = (Variant::Type)_code_ptr[ip + 2];
+ GET_VARIANT_PTR(dst, 3);
+
+ GD_ERR_BREAK(var_type < 0 || var_type >= Variant::VARIANT_MAX);
+
+ *dst = value->get_type() == var_type;
+ ip += 4;
+ }
+ DISPATCH_OPCODE;
+
OPCODE(OPCODE_SET) {
CHECK_SPACE(3);
diff --git a/modules/gdscript/gdscript_function.h b/modules/gdscript/gdscript_function.h
index 3ce84290fd..633cca35d3 100644
--- a/modules/gdscript/gdscript_function.h
+++ b/modules/gdscript/gdscript_function.h
@@ -136,6 +136,7 @@ public:
enum Opcode {
OPCODE_OPERATOR,
OPCODE_EXTENDS_TEST,
+ OPCODE_IS_BUILTIN,
OPCODE_SET,
OPCODE_GET,
OPCODE_SET_NAMED,
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index a3f5e1819e..7502f09d8a 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -861,6 +861,20 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s
op->arguments.push_back(subexpr);
expr=op;*/
+ } else if (tokenizer->get_token() == GDScriptTokenizer::TK_PR_IS && tokenizer->get_token(1) == GDScriptTokenizer::TK_BUILT_IN_TYPE) {
+ // 'is' operator with built-in type
+ OperatorNode *op = alloc_node<OperatorNode>();
+ op->op = OperatorNode::OP_IS_BUILTIN;
+ op->arguments.push_back(expr);
+
+ tokenizer->advance();
+
+ TypeNode *tn = alloc_node<TypeNode>();
+ tn->vtype = tokenizer->get_token_type();
+ op->arguments.push_back(tn);
+ tokenizer->advance();
+
+ expr = op;
} else if (tokenizer->get_token() == GDScriptTokenizer::TK_BRACKET_OPEN) {
// array
tokenizer->advance();
@@ -1071,6 +1085,15 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s
expr = op;
+ } else if (tokenizer->get_token() == GDScriptTokenizer::TK_BUILT_IN_TYPE && expression.size() > 0 && expression[expression.size() - 1].is_op && expression[expression.size() - 1].op == OperatorNode::OP_IS) {
+ Expression e = expression[expression.size() - 1];
+ e.op = OperatorNode::OP_IS_BUILTIN;
+ expression.write[expression.size() - 1] = e;
+
+ TypeNode *tn = alloc_node<TypeNode>();
+ tn->vtype = tokenizer->get_token_type();
+ expr = tn;
+ tokenizer->advance();
} else {
//find list [ or find dictionary {
@@ -1329,6 +1352,7 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s
switch (expression[i].op) {
case OperatorNode::OP_IS:
+ case OperatorNode::OP_IS_BUILTIN:
priority = -1;
break; //before anything
@@ -3915,14 +3939,15 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "FLAGS") {
- //current_export.hint=PROPERTY_HINT_ALL_FLAGS;
tokenizer->advance();
if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
+ ERR_EXPLAIN("Exporting bit flags hint requires string constants.");
+ WARN_DEPRECATED
break;
}
if (tokenizer->get_token() != GDScriptTokenizer::TK_COMMA) {
- _set_error("Expected ')' or ',' in bit flags hint.");
+ _set_error("Expected ',' in bit flags hint.");
return;
}
@@ -5793,6 +5818,13 @@ GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) {
case Node::TYPE_CONSTANT: {
node_type = _type_from_variant(static_cast<ConstantNode *>(p_node)->value);
} break;
+ case Node::TYPE_TYPE: {
+ TypeNode *tn = static_cast<TypeNode *>(p_node);
+ node_type.has_type = true;
+ node_type.is_meta_type = true;
+ node_type.kind = DataType::BUILTIN;
+ node_type.builtin_type = tn->vtype;
+ } break;
case Node::TYPE_ARRAY: {
node_type.has_type = true;
node_type.kind = DataType::BUILTIN;
@@ -5896,7 +5928,8 @@ GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) {
// yield can return anything
node_type.has_type = false;
} break;
- case OperatorNode::OP_IS: {
+ case OperatorNode::OP_IS:
+ case OperatorNode::OP_IS_BUILTIN: {
if (op->arguments.size() != 2) {
_set_error("Parser bug: binary operation without 2 arguments.", op->line);
@@ -5913,8 +5946,11 @@ GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) {
}
type_type.is_meta_type = false; // Test the actual type
if (!_is_type_compatible(type_type, value_type) && !_is_type_compatible(value_type, type_type)) {
- // TODO: Make this a warning?
- _set_error("A value of type '" + value_type.to_string() + "' will never be an instance of '" + type_type.to_string() + "'.", op->line);
+ if (op->op == OperatorNode::OP_IS) {
+ _set_error("A value of type '" + value_type.to_string() + "' will never be an instance of '" + type_type.to_string() + "'.", op->line);
+ } else {
+ _set_error("A value of type '" + value_type.to_string() + "' will never be of type '" + type_type.to_string() + "'.", op->line);
+ }
return DataType();
}
}
diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h
index dbe523a0b9..3c51e3f372 100644
--- a/modules/gdscript/gdscript_parser.h
+++ b/modules/gdscript/gdscript_parser.h
@@ -345,6 +345,7 @@ public:
OP_PARENT_CALL,
OP_YIELD,
OP_IS,
+ OP_IS_BUILTIN,
//indexing operator
OP_INDEX,
OP_INDEX_NAMED,
diff --git a/modules/mono/glue/cs_files/Basis.cs b/modules/mono/glue/cs_files/Basis.cs
index c280d32c61..10286f3832 100644
--- a/modules/mono/glue/cs_files/Basis.cs
+++ b/modules/mono/glue/cs_files/Basis.cs
@@ -426,7 +426,7 @@ namespace Godot
public Basis(Quat quat)
{
- real_t s = 2.0f / quat.LengthSquared();
+ real_t s = 2.0f / quat.LengthSquared;
real_t xs = quat.x * s;
real_t ys = quat.y * s;
diff --git a/modules/mono/glue/cs_files/Quat.cs b/modules/mono/glue/cs_files/Quat.cs
index c69c55d997..eaa027eb69 100644
--- a/modules/mono/glue/cs_files/Quat.cs
+++ b/modules/mono/glue/cs_files/Quat.cs
@@ -11,18 +11,11 @@ namespace Godot
[StructLayout(LayoutKind.Sequential)]
public struct Quat : IEquatable<Quat>
{
- private static readonly Quat identity = new Quat(0f, 0f, 0f, 1f);
-
public real_t x;
public real_t y;
public real_t z;
public real_t w;
- public static Quat Identity
- {
- get { return identity; }
- }
-
public real_t this[int index]
{
get
@@ -63,6 +56,16 @@ namespace Godot
}
}
+ public real_t Length
+ {
+ get { return Mathf.Sqrt(LengthSquared); }
+ }
+
+ public real_t LengthSquared
+ {
+ get { return Dot(this); }
+ }
+
public Quat CubicSlerp(Quat b, Quat preA, Quat postB, real_t t)
{
real_t t2 = (1.0f - t) * t * 2f;
@@ -76,24 +79,20 @@ namespace Godot
return x * b.x + y * b.y + z * b.z + w * b.w;
}
- public Quat Inverse()
- {
- return new Quat(-x, -y, -z, w);
- }
-
- public real_t Length()
+ public Vector3 GetEuler()
{
- return Mathf.Sqrt(LengthSquared());
+ var basis = new Basis(this);
+ return basis.GetEuler();
}
- public real_t LengthSquared()
+ public Quat Inverse()
{
- return Dot(this);
+ return new Quat(-x, -y, -z, w);
}
public Quat Normalized()
{
- return this / Length();
+ return this / Length;
}
public void Set(real_t x, real_t y, real_t z, real_t w)
@@ -103,12 +102,20 @@ namespace Godot
this.z = z;
this.w = w;
}
+
public void Set(Quat q)
{
- x = q.x;
- y = q.y;
- z = q.z;
- w = q.w;
+ this = q;
+ }
+
+ public void SetAxisAngle(Vector3 axis, real_t angle)
+ {
+ this = new Quat(axis, angle);
+ }
+
+ public void SetEuler(Vector3 eulerYXZ)
+ {
+ this = new Quat(eulerYXZ);
}
public Quat Slerp(Quat b, real_t t)
@@ -192,6 +199,9 @@ namespace Godot
return new Vector3(q.x, q.y, q.z);
}
+ // Static Readonly Properties
+ public static Quat Identity { get; } = new Quat(0f, 0f, 0f, 1f);
+
// Constructors
public Quat(real_t x, real_t y, real_t z, real_t w)
{
@@ -199,15 +209,46 @@ namespace Godot
this.y = y;
this.z = z;
this.w = w;
- }
+ }
+
+ public bool IsNormalized()
+ {
+ return Mathf.Abs(LengthSquared - 1) <= Mathf.Epsilon;
+ }
+
public Quat(Quat q)
- {
- x = q.x;
- y = q.y;
- z = q.z;
- w = q.w;
+ {
+ this = q;
+ }
+
+ public Quat(Basis basis)
+ {
+ this = basis.Quat();
}
-
+
+ public Quat(Vector3 eulerYXZ)
+ {
+ real_t half_a1 = eulerYXZ.y * (real_t)0.5;
+ real_t half_a2 = eulerYXZ.x * (real_t)0.5;
+ real_t half_a3 = eulerYXZ.z * (real_t)0.5;
+
+ // R = Y(a1).X(a2).Z(a3) convention for Euler angles.
+ // Conversion to quaternion as listed in https://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/19770024290.pdf (page A-6)
+ // a3 is the angle of the first rotation, following the notation in this reference.
+
+ real_t cos_a1 = Mathf.Cos(half_a1);
+ real_t sin_a1 = Mathf.Sin(half_a1);
+ real_t cos_a2 = Mathf.Cos(half_a2);
+ real_t sin_a2 = Mathf.Sin(half_a2);
+ real_t cos_a3 = Mathf.Cos(half_a3);
+ real_t sin_a3 = Mathf.Sin(half_a3);
+
+ x = sin_a1 * cos_a2 * sin_a3 + cos_a1 * sin_a2 * cos_a3;
+ y = sin_a1 * cos_a2 * cos_a3 - cos_a1 * sin_a2 * sin_a3;
+ z = -sin_a1 * sin_a2 * cos_a3 + cos_a1 * cos_a2 * sin_a3;
+ w = sin_a1 * sin_a2 * sin_a3 + cos_a1 * cos_a2 * cos_a3;
+ }
+
public Quat(Vector3 axis, real_t angle)
{
real_t d = axis.Length();
diff --git a/modules/squish/image_compress_squish.cpp b/modules/squish/image_compress_squish.cpp
index 653dd82351..bb8a4bdbea 100644
--- a/modules/squish/image_compress_squish.cpp
+++ b/modules/squish/image_compress_squish.cpp
@@ -193,8 +193,8 @@ void image_compress_squish(Image *p_image, float p_lossy_quality, Image::Compres
int src_ofs = p_image->get_mipmap_offset(i);
squish::CompressImage(&rb[src_ofs], w, h, &wb[dst_ofs], squish_comp);
dst_ofs += (MAX(4, bw) * MAX(4, bh)) >> shift;
- w >>= 1;
- h >>= 1;
+ w = MAX(w / 2, 1);
+ h = MAX(h / 2, 1);
}
rb = PoolVector<uint8_t>::Read();