Allow booleanization of all types
We now allow booleanization of all types. This means that empty versions of all types now evaluate to false. So a Vector2(0,0), Dictionary(), etc. This allows you to write GDScript like: if not Dictionary(): print("Empty dict") Booleanization can now also no longer fail. There is no more valid flag, this changes Variant and GDNative API.
This commit is contained in:
parent
85641c545b
commit
833c3917b2
@ -390,7 +390,7 @@ public:
|
||||
uint32_t hash() const;
|
||||
|
||||
bool hash_compare(const Variant &p_variant) const;
|
||||
bool booleanize(bool &valid) const;
|
||||
bool booleanize() const;
|
||||
|
||||
void static_assign(const Variant &p_variant);
|
||||
static void get_constructor_list(Variant::Type p_type, List<MethodInfo> *p_list);
|
||||
|
@ -143,56 +143,13 @@
|
||||
|
||||
Variant::operator bool() const {
|
||||
|
||||
bool b;
|
||||
return booleanize(b);
|
||||
return booleanize();
|
||||
}
|
||||
|
||||
bool Variant::booleanize(bool &r_valid) const {
|
||||
|
||||
r_valid = true;
|
||||
switch (type) {
|
||||
case NIL:
|
||||
return false;
|
||||
case BOOL:
|
||||
return _data._bool;
|
||||
case INT:
|
||||
return _data._int;
|
||||
case REAL:
|
||||
return _data._real;
|
||||
case STRING:
|
||||
return (*reinterpret_cast<const String *>(_data._mem)) != "";
|
||||
case VECTOR2:
|
||||
case RECT2:
|
||||
case TRANSFORM2D:
|
||||
case VECTOR3:
|
||||
case PLANE:
|
||||
case RECT3:
|
||||
case QUAT:
|
||||
case BASIS:
|
||||
case TRANSFORM:
|
||||
case COLOR:
|
||||
case _RID:
|
||||
return (*reinterpret_cast<const RID *>(_data._mem)).is_valid();
|
||||
case OBJECT:
|
||||
return _get_obj().obj;
|
||||
case NODE_PATH:
|
||||
return (*reinterpret_cast<const NodePath *>(_data._mem)) != NodePath();
|
||||
case DICTIONARY:
|
||||
case ARRAY:
|
||||
case POOL_BYTE_ARRAY:
|
||||
case POOL_INT_ARRAY:
|
||||
case POOL_REAL_ARRAY:
|
||||
case POOL_STRING_ARRAY:
|
||||
case POOL_VECTOR2_ARRAY:
|
||||
case POOL_VECTOR3_ARRAY:
|
||||
case POOL_COLOR_ARRAY:
|
||||
r_valid = false;
|
||||
return false;
|
||||
default: {
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
// We consider all unitialized or empty types to be false based on the type's
|
||||
// zeroiness.
|
||||
bool Variant::booleanize() const {
|
||||
return !is_zero();
|
||||
}
|
||||
|
||||
#define _RETURN(m_what) \
|
||||
@ -403,12 +360,6 @@ bool Variant::booleanize(bool &r_valid) const {
|
||||
_RETURN(sum); \
|
||||
}
|
||||
|
||||
#define DEFAULT_OP_FAIL(m_name) \
|
||||
case m_name: { \
|
||||
r_valid = false; \
|
||||
return; \
|
||||
}
|
||||
|
||||
void Variant::evaluate(const Operator &p_op, const Variant &p_a,
|
||||
const Variant &p_b, Variant &r_ret, bool &r_valid) {
|
||||
|
||||
@ -1177,12 +1128,8 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
|
||||
|
||||
SWITCH_OP(math, OP_AND, p_a.type) {
|
||||
CASE_TYPE_ALL(math, OP_AND) {
|
||||
bool l = p_a.booleanize(r_valid);
|
||||
if (!r_valid)
|
||||
return;
|
||||
bool r = p_b.booleanize(r_valid);
|
||||
if (!r_valid)
|
||||
return;
|
||||
bool l = p_a.booleanize();
|
||||
bool r = p_b.booleanize();
|
||||
|
||||
_RETURN(l && r);
|
||||
}
|
||||
@ -1190,12 +1137,8 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
|
||||
|
||||
SWITCH_OP(math, OP_OR, p_a.type) {
|
||||
CASE_TYPE_ALL(math, OP_OR) {
|
||||
bool l = p_a.booleanize(r_valid);
|
||||
if (!r_valid)
|
||||
return;
|
||||
bool r = p_b.booleanize(r_valid);
|
||||
if (!r_valid)
|
||||
return;
|
||||
bool l = p_a.booleanize();
|
||||
bool r = p_b.booleanize();
|
||||
|
||||
_RETURN(l || r);
|
||||
}
|
||||
@ -1203,12 +1146,8 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
|
||||
|
||||
SWITCH_OP(math, OP_XOR, p_a.type) {
|
||||
CASE_TYPE_ALL(math, OP_XOR) {
|
||||
bool l = p_a.booleanize(r_valid);
|
||||
if (!r_valid)
|
||||
return;
|
||||
bool r = p_b.booleanize(r_valid);
|
||||
if (!r_valid)
|
||||
return;
|
||||
bool l = p_a.booleanize();
|
||||
bool r = p_b.booleanize();
|
||||
|
||||
_RETURN((l || r) && !(l && r));
|
||||
}
|
||||
@ -1216,9 +1155,7 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a,
|
||||
|
||||
SWITCH_OP(math, OP_NOT, p_a.type) {
|
||||
CASE_TYPE_ALL(math, OP_NOT) {
|
||||
bool l = p_a.booleanize(r_valid);
|
||||
if (!r_valid)
|
||||
return;
|
||||
bool l = p_a.booleanize();
|
||||
_RETURN(!l);
|
||||
}
|
||||
}
|
||||
|
@ -480,10 +480,9 @@ godot_bool GDAPI godot_variant_hash_compare(const godot_variant *p_self, const g
|
||||
return self->hash_compare(*other);
|
||||
}
|
||||
|
||||
godot_bool GDAPI godot_variant_booleanize(const godot_variant *p_self, godot_bool *r_valid) {
|
||||
godot_bool GDAPI godot_variant_booleanize(const godot_variant *p_self) {
|
||||
const Variant *self = (const Variant *)p_self;
|
||||
bool &valid = *r_valid;
|
||||
return self->booleanize(valid);
|
||||
return self->booleanize();
|
||||
}
|
||||
|
||||
void GDAPI godot_variant_destroy(godot_variant *p_self) {
|
||||
|
@ -190,7 +190,7 @@ godot_bool GDAPI godot_variant_operator_less(const godot_variant *p_self, const
|
||||
|
||||
godot_bool GDAPI godot_variant_hash_compare(const godot_variant *p_self, const godot_variant *p_other);
|
||||
|
||||
godot_bool GDAPI godot_variant_booleanize(const godot_variant *p_self, godot_bool *r_valid);
|
||||
godot_bool GDAPI godot_variant_booleanize(const godot_variant *p_self);
|
||||
|
||||
void GDAPI godot_variant_destroy(godot_variant *p_self);
|
||||
|
||||
|
@ -534,7 +534,7 @@ extern "C" {
|
||||
GDAPI_FUNC(godot_variant_operator_equal, godot_bool, const godot_variant *p_self, const godot_variant *p_other) \
|
||||
GDAPI_FUNC(godot_variant_operator_less, godot_bool, const godot_variant *p_self, const godot_variant *p_other) \
|
||||
GDAPI_FUNC(godot_variant_hash_compare, godot_bool, const godot_variant *p_self, const godot_variant *p_other) \
|
||||
GDAPI_FUNC(godot_variant_booleanize, godot_bool, const godot_variant *p_self, godot_bool *r_valid) \
|
||||
GDAPI_FUNC(godot_variant_booleanize, godot_bool, const godot_variant *p_self) \
|
||||
GDAPI_FUNC_VOID(godot_variant_destroy, godot_variant *p_self) \
|
||||
GDAPI_FUNC_VOID(godot_string_new, godot_string *r_dest) \
|
||||
GDAPI_FUNC_VOID(godot_string_new_copy, godot_string *r_dest, const godot_string *p_src) \
|
||||
|
@ -982,15 +982,8 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
|
||||
|
||||
GET_VARIANT_PTR(test, 1);
|
||||
|
||||
bool valid;
|
||||
bool result = test->booleanize(valid);
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (!valid) {
|
||||
bool result = test->booleanize();
|
||||
|
||||
err_text = "cannot evaluate conditional expression of type: " + Variant::get_type_name(test->get_type());
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
if (result) {
|
||||
int to = _code_ptr[ip + 2];
|
||||
GD_ERR_BREAK(to < 0 || to > _code_size);
|
||||
@ -1006,15 +999,8 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
|
||||
|
||||
GET_VARIANT_PTR(test, 1);
|
||||
|
||||
bool valid;
|
||||
bool result = test->booleanize(valid);
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (!valid) {
|
||||
bool result = test->booleanize();
|
||||
|
||||
err_text = "cannot evaluate conditional expression of type: " + Variant::get_type_name(test->get_type());
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
if (!result) {
|
||||
int to = _code_ptr[ip + 2];
|
||||
GD_ERR_BREAK(to < 0 || to > _code_size);
|
||||
@ -1107,14 +1093,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
|
||||
GET_VARIANT_PTR(test, 1);
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
bool valid;
|
||||
bool result = test->booleanize(valid);
|
||||
|
||||
if (!valid) {
|
||||
|
||||
err_text = "cannot evaluate conditional expression of type: " + Variant::get_type_name(test->get_type());
|
||||
break;
|
||||
}
|
||||
bool result = test->booleanize();
|
||||
|
||||
if (!result) {
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user