diff options
39 files changed, 624 insertions, 430 deletions
diff --git a/SConstruct b/SConstruct index f134dfddac..d82ceb514b 100644 --- a/SConstruct +++ b/SConstruct @@ -67,7 +67,6 @@ if "TERM" in os.environ: env_base.AppendENVPath("PATH", os.getenv("PATH")) env_base.AppendENVPath("PKG_CONFIG_PATH", os.getenv("PKG_CONFIG_PATH")) env_base.disabled_modules = [] -env_base.use_ptrcall = False env_base.module_version_string = "" env_base.msvc = False @@ -561,8 +560,6 @@ if selected_platform in platform_list: env["LIBSUFFIX"] = suffix + env["LIBSUFFIX"] env["SHLIBSUFFIX"] = suffix + env["SHLIBSUFFIX"] - if env.use_ptrcall: - env.Append(CPPDEFINES=["PTRCALL_ENABLED"]) if env["tools"]: env.Append(CPPDEFINES=["TOOLS_ENABLED"]) if env["disable_3d"]: diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp index aa954ed300..8b8aff3e9e 100644 --- a/core/config/project_settings.cpp +++ b/core/config/project_settings.cpp @@ -524,10 +524,6 @@ bool ProjectSettings::has_setting(String p_var) const { return props.has(p_var); } -void ProjectSettings::set_registering_order(bool p_enable) { - registering_order = p_enable; -} - Error ProjectSettings::_load_settings_binary(const String &p_path) { Error err; FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err); diff --git a/core/config/project_settings.h b/core/config/project_settings.h index a8c9adc587..5a16248c76 100644 --- a/core/config/project_settings.h +++ b/core/config/project_settings.h @@ -76,7 +76,6 @@ protected: } }; - bool registering_order = true; int last_order = NO_BUILTIN_ORDER_BASE; int last_builtin_order = 0; Map<StringName, VariantContainer> props; @@ -160,8 +159,6 @@ public: bool is_using_datapack() const; - void set_registering_order(bool p_enable); - bool has_custom_feature(const String &p_feature) const; Map<StringName, AutoloadInfo> get_autoload_list() const; diff --git a/core/object/method_bind.h b/core/object/method_bind.h index ddd6ab6baa..bd308c9630 100644 --- a/core/object/method_bind.h +++ b/core/object/method_bind.h @@ -123,10 +123,7 @@ public: _FORCE_INLINE_ int get_argument_count() const { return argument_count; }; virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) = 0; - -#ifdef PTRCALL_ENABLED virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) = 0; -#endif StringName get_name() const; void set_name(const StringName &p_name); @@ -205,11 +202,9 @@ public: #endif } -#ifdef PTRCALL_ENABLED virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) { - ERR_FAIL(); //can't call - } //todo -#endif + ERR_FAIL(); // Can't call. + } void set_method(NativeCall p_method) { call_method = p_method; } virtual bool is_const() const { return false; } @@ -289,7 +284,6 @@ public: return Variant(); } -#ifdef PTRCALL_ENABLED virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) { #ifdef TYPED_METHOD_BIND call_with_ptr_args<T, P...>(static_cast<T *>(p_object), method, p_args); @@ -297,7 +291,6 @@ public: call_with_ptr_args<MB_T, P...>((MB_T *)(p_object), method, p_args); #endif } -#endif MethodBindT(void (MB_T::*p_method)(P...)) { method = p_method; @@ -370,7 +363,6 @@ public: return Variant(); } -#ifdef PTRCALL_ENABLED virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) { #ifdef TYPED_METHOD_BIND call_with_ptr_argsc<T, P...>(static_cast<T *>(p_object), method, p_args); @@ -378,7 +370,6 @@ public: call_with_ptr_argsc<MB_T, P...>((MB_T *)(p_object), method, p_args); #endif } -#endif MethodBindTC(void (MB_T::*p_method)(P...) const) { method = p_method; @@ -462,7 +453,6 @@ public: return ret; } -#ifdef PTRCALL_ENABLED virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) { #ifdef TYPED_METHOD_BIND call_with_ptr_args_ret<T, R, P...>(static_cast<T *>(p_object), method, p_args, r_ret); @@ -470,7 +460,6 @@ public: call_with_ptr_args_ret<MB_T, R, P...>((MB_T *)(p_object), method, p_args, r_ret); #endif } -#endif MethodBindTR(R (MB_T::*p_method)(P...)) { method = p_method; @@ -555,7 +544,6 @@ public: return ret; } -#ifdef PTRCALL_ENABLED virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) { #ifdef TYPED_METHOD_BIND call_with_ptr_args_retc<T, R, P...>(static_cast<T *>(p_object), method, p_args, r_ret); @@ -563,7 +551,6 @@ public: call_with_ptr_args_retc<MB_T, R, P...>((MB_T *)(p_object), method, p_args, r_ret); #endif } -#endif MethodBindTRC(R (MB_T::*p_method)(P...) const) { method = p_method; diff --git a/core/object/reference.h b/core/object/reference.h index 575f1cd914..0eb127f362 100644 --- a/core/object/reference.h +++ b/core/object/reference.h @@ -252,8 +252,6 @@ public: WeakRef() {} }; -#ifdef PTRCALL_ENABLED - template <class T> struct PtrToArg<Ref<T>> { _FORCE_INLINE_ static Ref<T> convert(const void *p_ptr) { @@ -272,8 +270,6 @@ struct PtrToArg<const Ref<T> &> { } }; -#endif // PTRCALL_ENABLED - #ifdef DEBUG_METHODS_ENABLED template <class T> diff --git a/core/variant/binder_common.h b/core/variant/binder_common.h index 2e38ce5b06..e950709526 100644 --- a/core/variant/binder_common.h +++ b/core/variant/binder_common.h @@ -63,8 +63,6 @@ struct VariantCaster<const T &> { } }; -#ifdef PTRCALL_ENABLED - #define VARIANT_ENUM_CAST(m_enum) \ MAKE_ENUM_TYPE_INFO(m_enum) \ template <> \ @@ -83,19 +81,6 @@ struct VariantCaster<const T &> { } \ }; -#else - -#define VARIANT_ENUM_CAST(m_enum) \ - MAKE_ENUM_TYPE_INFO(m_enum) \ - template <> \ - struct VariantCaster<m_enum> { \ - static _FORCE_INLINE_ m_enum cast(const Variant &p_variant) { \ - return (m_enum)p_variant.operator int(); \ - } \ - }; - -#endif - // Object enum casts must go here VARIANT_ENUM_CAST(Object::ConnectFlags); @@ -118,7 +103,7 @@ struct VariantCaster<char32_t> { return (char32_t)p_variant.operator int(); } }; -#ifdef PTRCALL_ENABLED + template <> struct PtrToArg<char32_t> { _FORCE_INLINE_ static char32_t convert(const void *p_ptr) { @@ -128,7 +113,6 @@ struct PtrToArg<char32_t> { *(int *)p_ptr = p_val; } }; -#endif template <typename T> struct VariantObjectClassChecker { @@ -228,8 +212,6 @@ void call_with_variant_argsc_helper(T *p_instance, void (T::*p_method)(P...) con (void)(p_args); //avoid warning } -#ifdef PTRCALL_ENABLED - template <class T, class... P, size_t... Is> void call_with_ptr_args_helper(T *p_instance, void (T::*p_method)(P...), const void **p_args, IndexSequence<Is...>) { (p_instance->*p_method)(PtrToArg<P>::convert(p_args[Is])...); @@ -255,8 +237,6 @@ void call_with_ptr_args_static_retc_helper(T *p_instance, R (*p_method)(T *, P.. PtrToArg<R>::encode(p_method(p_instance, PtrToArg<P>::convert(p_args[Is])...), r_ret); } -#endif // PTRCALL_ENABLED - template <class T, class... P, size_t... Is> void call_with_validated_variant_args_helper(T *p_instance, void (T::*p_method)(P...), const Variant **p_args, IndexSequence<Is...>) { (p_instance->*p_method)((VariantInternalAccessor<typename GetSimpleTypeT<P>::type_t>::get(p_args[Is]))...); @@ -450,8 +430,6 @@ void call_with_variant_args_retc_dv(T *p_instance, R (T::*p_method)(P...) const, call_with_variant_args_retc_helper(p_instance, p_method, args, r_ret, r_error, BuildIndexSequence<sizeof...(P)>{}); } -#ifdef PTRCALL_ENABLED - template <class T, class... P> void call_with_ptr_args(T *p_instance, void (T::*p_method)(P...), const void **p_args) { call_with_ptr_args_helper<T, P...>(p_instance, p_method, p_args, BuildIndexSequence<sizeof...(P)>{}); @@ -477,8 +455,6 @@ void call_with_ptr_args_static_retc(T *p_instance, R (*p_method)(T *, P...), con call_with_ptr_args_static_retc_helper<T, R, P...>(p_instance, p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{}); } -#endif // PTRCALL_ENABLED - template <class T, class... P> void call_with_validated_variant_args(Variant *base, void (T::*p_method)(P...), const Variant **p_args) { call_with_validated_variant_args_helper<T, P...>(VariantGetInternalPtr<T>::get_ptr(base), p_method, p_args, BuildIndexSequence<sizeof...(P)>{}); diff --git a/core/variant/method_ptrcall.h b/core/variant/method_ptrcall.h index 936de145f8..40fa3543dc 100644 --- a/core/variant/method_ptrcall.h +++ b/core/variant/method_ptrcall.h @@ -36,11 +36,8 @@ #include "core/typedefs.h" #include "core/variant/variant.h" -#ifdef PTRCALL_ENABLED - template <class T> -struct PtrToArg { -}; +struct PtrToArg {}; #define MAKE_PTRARG(m_type) \ template <> \ @@ -146,7 +143,7 @@ MAKE_PTRARG(PackedVector3Array); MAKE_PTRARG(PackedColorArray); MAKE_PTRARG_BY_REFERENCE(Variant); -//this is for Object +// This is for Object. template <class T> struct PtrToArg<T *> { @@ -170,7 +167,7 @@ struct PtrToArg<const T *> { } }; -//this is for ObjectID +// This is for ObjectID. template <> struct PtrToArg<ObjectID> { @@ -183,7 +180,7 @@ struct PtrToArg<ObjectID> { } }; -//this is for the special cases used by Variant +// This is for the special cases used by Variant. #define MAKE_VECARG(m_type) \ template <> \ @@ -274,18 +271,11 @@ struct PtrToArg<ObjectID> { return ret; \ } \ } -/* -MAKE_VECARG(String); -MAKE_VECARG(uint8_t); -MAKE_VECARG(int); -MAKE_VECARG(float); -MAKE_VECARG(Vector2); -MAKE_VECARG(Vector3); -MAKE_VECARG(Color); -*/ + MAKE_VECARG_ALT(String, StringName); -//for stuff that gets converted to Array vectors +// For stuff that gets converted to Array vectors. + #define MAKE_VECARR(m_type) \ template <> \ struct PtrToArg<Vector<m_type>> { \ @@ -429,6 +419,7 @@ struct PtrToArg<Vector<Face3>> { } } }; + template <> struct PtrToArg<const Vector<Face3> &> { _FORCE_INLINE_ static Vector<Face3> convert(const void *p_ptr) { @@ -450,4 +441,3 @@ struct PtrToArg<const Vector<Face3> &> { }; #endif // METHOD_PTRCALL_H -#endif diff --git a/core/variant/typed_array.h b/core/variant/typed_array.h index ff42cb687e..2f11f22ff8 100644 --- a/core/variant/typed_array.h +++ b/core/variant/typed_array.h @@ -120,8 +120,6 @@ MAKE_TYPED_ARRAY(Vector<Vector2>, Variant::PACKED_VECTOR2_ARRAY) MAKE_TYPED_ARRAY(Vector<Vector3>, Variant::PACKED_VECTOR3_ARRAY) MAKE_TYPED_ARRAY(Vector<Color>, Variant::PACKED_COLOR_ARRAY) -#ifdef PTRCALL_ENABLED - template <class T> struct PtrToArg<TypedArray<T>> { _FORCE_INLINE_ static TypedArray<T> convert(const void *p_ptr) { @@ -140,8 +138,6 @@ struct PtrToArg<const TypedArray<T> &> { } }; -#endif // PTRCALL_ENABLED - #ifdef DEBUG_METHODS_ENABLED template <class T> diff --git a/core/variant/variant.h b/core/variant/variant.h index 26280948be..d87078b5da 100644 --- a/core/variant/variant.h +++ b/core/variant/variant.h @@ -370,7 +370,6 @@ public: #ifdef NEED_LONG_INT Variant(signed long p_long); // real one Variant(unsigned long p_long); -//Variant(long unsigned int p_long); #endif Variant(signed short p_short); // real one Variant(unsigned short p_short); @@ -471,10 +470,8 @@ public: static Variant::Type get_operator_return_type(Operator p_operator, Type p_type_a, Type p_type_b); typedef void (*ValidatedOperatorEvaluator)(const Variant *left, const Variant *right, Variant *r_ret); static ValidatedOperatorEvaluator get_validated_operator_evaluator(Operator p_operator, Type p_type_a, Type p_type_b); -#ifdef PTRCALL_ENABLED typedef void (*PTROperatorEvaluator)(const void *left, const void *right, void *r_ret); static PTROperatorEvaluator get_ptr_operator_evaluator(Operator p_operator, Type p_type_a, Type p_type_b); -#endif void zero(); Variant duplicate(bool deep = false) const; diff --git a/core/variant/variant_op.cpp b/core/variant/variant_op.cpp index 74ecbfb8d1..07b024ecb4 100644 --- a/core/variant/variant_op.cpp +++ b/core/variant/variant_op.cpp @@ -47,11 +47,9 @@ public: VariantTypeChanger<R>::change(r_ret); *VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) + *VariantGetInternalPtr<B>::get_ptr(right); } -#ifdef PTRCALL_ENABLED static void ptr_evaluate(const void *left, const void *right, void *r_ret) { PtrToArg<R>::encode(PtrToArg<A>::convert(left) + PtrToArg<B>::convert(right), r_ret); } -#endif static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; } }; @@ -68,11 +66,9 @@ public: VariantTypeChanger<R>::change(r_ret); *VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) - *VariantGetInternalPtr<B>::get_ptr(right); } -#ifdef PTRCALL_ENABLED static void ptr_evaluate(const void *left, const void *right, void *r_ret) { PtrToArg<R>::encode(PtrToArg<A>::convert(left) - PtrToArg<B>::convert(right), r_ret); } -#endif static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; } }; @@ -89,11 +85,9 @@ public: VariantTypeChanger<R>::change(r_ret); *VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) * *VariantGetInternalPtr<B>::get_ptr(right); } -#ifdef PTRCALL_ENABLED static void ptr_evaluate(const void *left, const void *right, void *r_ret) { PtrToArg<R>::encode(PtrToArg<A>::convert(left) * PtrToArg<B>::convert(right), r_ret); } -#endif static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; } }; @@ -110,11 +104,9 @@ public: VariantTypeChanger<R>::change(r_ret); *VariantGetInternalPtr<R>::get_ptr(r_ret) = VariantGetInternalPtr<A>::get_ptr(left)->xform(*VariantGetInternalPtr<B>::get_ptr(right)); } -#ifdef PTRCALL_ENABLED static void ptr_evaluate(const void *left, const void *right, void *r_ret) { PtrToArg<R>::encode(PtrToArg<A>::convert(left).xform(PtrToArg<B>::convert(right)), r_ret); } -#endif static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; } }; @@ -131,11 +123,9 @@ public: VariantTypeChanger<R>::change(r_ret); *VariantGetInternalPtr<R>::get_ptr(r_ret) = VariantGetInternalPtr<B>::get_ptr(right)->xform_inv(*VariantGetInternalPtr<A>::get_ptr(left)); } -#ifdef PTRCALL_ENABLED static void ptr_evaluate(const void *left, const void *right, void *r_ret) { PtrToArg<R>::encode(PtrToArg<B>::convert(right).xform_inv(PtrToArg<A>::convert(left)), r_ret); } -#endif static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; } }; @@ -152,11 +142,9 @@ public: VariantTypeChanger<R>::change(r_ret); *VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) / *VariantGetInternalPtr<B>::get_ptr(right); } -#ifdef PTRCALL_ENABLED static void ptr_evaluate(const void *left, const void *right, void *r_ret) { PtrToArg<R>::encode(PtrToArg<A>::convert(left) / PtrToArg<B>::convert(right), r_ret); } -#endif static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; } }; @@ -178,11 +166,9 @@ public: VariantTypeChanger<R>::change(r_ret); *VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) / *VariantGetInternalPtr<B>::get_ptr(right); } -#ifdef PTRCALL_ENABLED static void ptr_evaluate(const void *left, const void *right, void *r_ret) { PtrToArg<R>::encode(PtrToArg<A>::convert(left) / PtrToArg<B>::convert(right), r_ret); } -#endif static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; } }; @@ -199,11 +185,9 @@ public: VariantTypeChanger<R>::change(r_ret); *VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) % *VariantGetInternalPtr<B>::get_ptr(right); } -#ifdef PTRCALL_ENABLED static void ptr_evaluate(const void *left, const void *right, void *r_ret) { PtrToArg<R>::encode(PtrToArg<A>::convert(left) % PtrToArg<B>::convert(right), r_ret); } -#endif static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; } }; @@ -225,11 +209,9 @@ public: VariantTypeChanger<R>::change(r_ret); *VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) % *VariantGetInternalPtr<B>::get_ptr(right); } -#ifdef PTRCALL_ENABLED static void ptr_evaluate(const void *left, const void *right, void *r_ret) { PtrToArg<R>::encode(PtrToArg<A>::convert(left) % PtrToArg<B>::convert(right), r_ret); } -#endif static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; } }; @@ -245,11 +227,9 @@ public: VariantTypeChanger<R>::change(r_ret); *VariantGetInternalPtr<R>::get_ptr(r_ret) = -*VariantGetInternalPtr<A>::get_ptr(left); } -#ifdef PTRCALL_ENABLED static void ptr_evaluate(const void *left, const void *right, void *r_ret) { PtrToArg<R>::encode(-PtrToArg<A>::convert(left), r_ret); } -#endif static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; } }; @@ -265,11 +245,9 @@ public: VariantTypeChanger<R>::change(r_ret); *VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left); } -#ifdef PTRCALL_ENABLED static void ptr_evaluate(const void *left, const void *right, void *r_ret) { PtrToArg<R>::encode(PtrToArg<A>::convert(left), r_ret); } -#endif static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; } }; @@ -286,11 +264,9 @@ public: VariantTypeChanger<R>::change(r_ret); *VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) << *VariantGetInternalPtr<B>::get_ptr(right); } -#ifdef PTRCALL_ENABLED static void ptr_evaluate(const void *left, const void *right, void *r_ret) { PtrToArg<R>::encode(PtrToArg<A>::convert(left) << PtrToArg<B>::convert(right), r_ret); } -#endif static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; } }; @@ -307,11 +283,9 @@ public: VariantTypeChanger<R>::change(r_ret); *VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) >> *VariantGetInternalPtr<B>::get_ptr(right); } -#ifdef PTRCALL_ENABLED static void ptr_evaluate(const void *left, const void *right, void *r_ret) { PtrToArg<R>::encode(PtrToArg<A>::convert(left) >> PtrToArg<B>::convert(right), r_ret); } -#endif static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; } }; @@ -328,11 +302,9 @@ public: VariantTypeChanger<R>::change(r_ret); *VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) | *VariantGetInternalPtr<B>::get_ptr(right); } -#ifdef PTRCALL_ENABLED static void ptr_evaluate(const void *left, const void *right, void *r_ret) { PtrToArg<R>::encode(PtrToArg<A>::convert(left) | PtrToArg<B>::convert(right), r_ret); } -#endif static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; } }; @@ -348,11 +320,9 @@ public: static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { *VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) & *VariantGetInternalPtr<B>::get_ptr(right); } -#ifdef PTRCALL_ENABLED static void ptr_evaluate(const void *left, const void *right, void *r_ret) { PtrToArg<R>::encode(PtrToArg<A>::convert(left) & PtrToArg<B>::convert(right), r_ret); } -#endif static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; } }; @@ -369,11 +339,9 @@ public: VariantTypeChanger<R>::change(r_ret); *VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) ^ *VariantGetInternalPtr<B>::get_ptr(right); } -#ifdef PTRCALL_ENABLED static void ptr_evaluate(const void *left, const void *right, void *r_ret) { PtrToArg<R>::encode(PtrToArg<A>::convert(left) ^ PtrToArg<B>::convert(right), r_ret); } -#endif static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; } }; @@ -389,11 +357,9 @@ public: VariantTypeChanger<R>::change(r_ret); *VariantGetInternalPtr<R>::get_ptr(r_ret) = ~*VariantGetInternalPtr<A>::get_ptr(left); } -#ifdef PTRCALL_ENABLED static void ptr_evaluate(const void *left, const void *right, void *r_ret) { PtrToArg<R>::encode(~PtrToArg<A>::convert(left), r_ret); } -#endif static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; } }; @@ -410,14 +376,12 @@ public: VariantTypeChanger<bool>::change(r_ret); *VariantGetInternalPtr<bool>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) == *VariantGetInternalPtr<B>::get_ptr(right); } -#ifdef PTRCALL_ENABLED static void ptr_evaluate(const void *left, const void *right, void *r_ret) { PtrToArg<bool>::encode(PtrToArg<A>::convert(left) == PtrToArg<B>::convert(right), r_ret); } -#endif static Variant::Type get_return_type() { return Variant::BOOL; } }; -//equalobject + class OperatorEvaluatorEqualObject { public: static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { @@ -432,11 +396,9 @@ public: VariantTypeChanger<bool>::change(r_ret); *VariantGetInternalPtr<bool>::get_ptr(r_ret) = a == b; } -#ifdef PTRCALL_ENABLED static void ptr_evaluate(const void *left, const void *right, void *r_ret) { PtrToArg<bool>::encode(PtrToArg<Object *>::convert(left) == PtrToArg<Object *>::convert(right), r_ret); } -#endif static Variant::Type get_return_type() { return Variant::BOOL; } }; @@ -452,11 +414,9 @@ public: VariantTypeChanger<bool>::change(r_ret); *VariantGetInternalPtr<bool>::get_ptr(r_ret) = a == nullptr; } -#ifdef PTRCALL_ENABLED static void ptr_evaluate(const void *left, const void *right, void *r_ret) { PtrToArg<bool>::encode(PtrToArg<Object *>::convert(left) == nullptr, r_ret); } -#endif static Variant::Type get_return_type() { return Variant::BOOL; } }; @@ -472,11 +432,9 @@ public: VariantTypeChanger<bool>::change(r_ret); *VariantGetInternalPtr<bool>::get_ptr(r_ret) = nullptr == b; } -#ifdef PTRCALL_ENABLED static void ptr_evaluate(const void *left, const void *right, void *r_ret) { PtrToArg<bool>::encode(nullptr == PtrToArg<Object *>::convert(right), r_ret); } -#endif static Variant::Type get_return_type() { return Variant::BOOL; } }; @@ -493,11 +451,9 @@ public: VariantTypeChanger<bool>::change(r_ret); *VariantGetInternalPtr<bool>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) != *VariantGetInternalPtr<B>::get_ptr(right); } -#ifdef PTRCALL_ENABLED static void ptr_evaluate(const void *left, const void *right, void *r_ret) { PtrToArg<bool>::encode(PtrToArg<A>::convert(left) != PtrToArg<B>::convert(right), r_ret); } -#endif static Variant::Type get_return_type() { return Variant::BOOL; } }; @@ -515,11 +471,9 @@ public: VariantTypeChanger<bool>::change(r_ret); *VariantGetInternalPtr<bool>::get_ptr(r_ret) = a != b; } -#ifdef PTRCALL_ENABLED static void ptr_evaluate(const void *left, const void *right, void *r_ret) { PtrToArg<bool>::encode(PtrToArg<Object *>::convert(left) != PtrToArg<Object *>::convert(right), r_ret); } -#endif static Variant::Type get_return_type() { return Variant::BOOL; } }; @@ -535,11 +489,9 @@ public: VariantTypeChanger<bool>::change(r_ret); *VariantGetInternalPtr<bool>::get_ptr(r_ret) = a != nullptr; } -#ifdef PTRCALL_ENABLED static void ptr_evaluate(const void *left, const void *right, void *r_ret) { PtrToArg<bool>::encode(PtrToArg<Object *>::convert(left) != nullptr, r_ret); } -#endif static Variant::Type get_return_type() { return Variant::BOOL; } }; @@ -555,11 +507,9 @@ public: VariantTypeChanger<bool>::change(r_ret); *VariantGetInternalPtr<bool>::get_ptr(r_ret) = nullptr != b; } -#ifdef PTRCALL_ENABLED static void ptr_evaluate(const void *left, const void *right, void *r_ret) { PtrToArg<bool>::encode(nullptr != PtrToArg<Object *>::convert(right), r_ret); } -#endif static Variant::Type get_return_type() { return Variant::BOOL; } }; @@ -576,11 +526,9 @@ public: VariantTypeChanger<bool>::change(r_ret); *VariantGetInternalPtr<bool>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) < *VariantGetInternalPtr<B>::get_ptr(right); } -#ifdef PTRCALL_ENABLED static void ptr_evaluate(const void *left, const void *right, void *r_ret) { PtrToArg<bool>::encode(PtrToArg<A>::convert(left) < PtrToArg<B>::convert(right), r_ret); } -#endif static Variant::Type get_return_type() { return Variant::BOOL; } }; @@ -597,11 +545,9 @@ public: VariantTypeChanger<bool>::change(r_ret); *VariantGetInternalPtr<bool>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) <= *VariantGetInternalPtr<B>::get_ptr(right); } -#ifdef PTRCALL_ENABLED static void ptr_evaluate(const void *left, const void *right, void *r_ret) { PtrToArg<bool>::encode(PtrToArg<A>::convert(left) <= PtrToArg<B>::convert(right), r_ret); } -#endif static Variant::Type get_return_type() { return Variant::BOOL; } }; @@ -618,11 +564,9 @@ public: VariantTypeChanger<bool>::change(r_ret); *VariantGetInternalPtr<bool>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) > *VariantGetInternalPtr<B>::get_ptr(right); } -#ifdef PTRCALL_ENABLED static void ptr_evaluate(const void *left, const void *right, void *r_ret) { PtrToArg<bool>::encode(PtrToArg<A>::convert(left) > PtrToArg<B>::convert(right), r_ret); } -#endif static Variant::Type get_return_type() { return Variant::BOOL; } }; @@ -639,11 +583,9 @@ public: VariantTypeChanger<bool>::change(r_ret); *VariantGetInternalPtr<bool>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) >= *VariantGetInternalPtr<B>::get_ptr(right); } -#ifdef PTRCALL_ENABLED static void ptr_evaluate(const void *left, const void *right, void *r_ret) { PtrToArg<bool>::encode(PtrToArg<A>::convert(left) >= PtrToArg<B>::convert(right), r_ret); } -#endif static Variant::Type get_return_type() { return Variant::BOOL; } }; @@ -660,12 +602,9 @@ public: VariantTypeChanger<bool>::change(r_ret); *VariantGetInternalPtr<bool>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) && *VariantGetInternalPtr<B>::get_ptr(right); } -#ifdef PTRCALL_ENABLED static void ptr_evaluate(const void *left, const void *right, void *r_ret) { PtrToArg<bool>::encode(PtrToArg<A>::convert(left) && PtrToArg<B>::convert(right), r_ret); } -#endif - static Variant::Type get_return_type() { return Variant::BOOL; } }; @@ -682,11 +621,9 @@ public: VariantTypeChanger<bool>::change(r_ret); *VariantGetInternalPtr<bool>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) || *VariantGetInternalPtr<B>::get_ptr(right); } -#ifdef PTRCALL_ENABLED static void ptr_evaluate(const void *left, const void *right, void *r_ret) { PtrToArg<bool>::encode(PtrToArg<A>::convert(left) || PtrToArg<B>::convert(right), r_ret); } -#endif static Variant::Type get_return_type() { return Variant::BOOL; } }; @@ -697,7 +634,6 @@ public: _FORCE_INLINE_ static bool xor_op(const A &a, const B &b) { return ((a) || (b)) && !((a) && (b)); } - static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left); const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right); @@ -708,12 +644,9 @@ public: VariantTypeChanger<bool>::change(r_ret); *VariantGetInternalPtr<bool>::get_ptr(r_ret) = xor_op(*VariantGetInternalPtr<A>::get_ptr(left), *VariantGetInternalPtr<B>::get_ptr(right)); } -#ifdef PTRCALL_ENABLED static void ptr_evaluate(const void *left, const void *right, void *r_ret) { PtrToArg<bool>::encode(xor_op(PtrToArg<A>::convert(left), PtrToArg<B>::convert(right)), r_ret); } -#endif - static Variant::Type get_return_type() { return Variant::BOOL; } }; @@ -729,11 +662,9 @@ public: VariantTypeChanger<bool>::change(r_ret); *VariantGetInternalPtr<bool>::get_ptr(r_ret) = !*VariantGetInternalPtr<A>::get_ptr(left); } -#ifdef PTRCALL_ENABLED static void ptr_evaluate(const void *left, const void *right, void *r_ret) { PtrToArg<bool>::encode(!PtrToArg<A>::convert(left)); } -#endif static Variant::Type get_return_type() { return Variant::BOOL; } }; @@ -764,14 +695,11 @@ public: VariantTypeChanger<Array>::change(r_ret); _add_arrays(*VariantGetInternalPtr<Array>::get_ptr(r_ret), *VariantGetInternalPtr<Array>::get_ptr(left), *VariantGetInternalPtr<Array>::get_ptr(right)); } -#ifdef PTRCALL_ENABLED static void ptr_evaluate(const void *left, const void *right, void *r_ret) { Array ret; _add_arrays(ret, PtrToArg<Array>::convert(left), PtrToArg<Array>::convert(right)); PtrToArg<Array>::encode(ret, r_ret); } -#endif - static Variant::Type get_return_type() { return Variant::ARRAY; } }; @@ -791,14 +719,11 @@ public: *VariantGetInternalPtr<Vector<T>>::get_ptr(r_ret) = *VariantGetInternalPtr<Vector<T>>::get_ptr(left); VariantGetInternalPtr<Vector<T>>::get_ptr(r_ret)->append_array(*VariantGetInternalPtr<Vector<T>>::get_ptr(right)); } -#ifdef PTRCALL_ENABLED static void ptr_evaluate(const void *left, const void *right, void *r_ret) { Vector<T> sum = PtrToArg<Vector<T>>::convert(left); sum.append_array(PtrToArg<Vector<T>>::convert(right)); PtrToArg<Vector<T>>::encode(sum, r_ret); } -#endif - static Variant::Type get_return_type() { return GetTypeInfo<Vector<T>>::VARIANT_TYPE; } }; @@ -819,16 +744,13 @@ public: *r_ret = do_mod(a, &r_valid); r_valid = true; } - static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { VariantTypeChanger<String>::change(r_ret); *VariantGetInternalPtr<String>::get_ptr(r_ret) = do_mod(*VariantGetInternalPtr<String>::get_ptr(left), nullptr); } -#ifdef PTRCALL_ENABLED static void ptr_evaluate(const void *left, const void *right, void *r_ret) { PtrToArg<String>::encode(do_mod(PtrToArg<String>::convert(left), nullptr), r_ret); } -#endif static Variant::Type get_return_type() { return Variant::STRING; } }; @@ -846,16 +768,13 @@ public: *r_ret = do_mod(a, *VariantGetInternalPtr<Array>::get_ptr(&p_right), &r_valid); r_valid = true; } - static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { VariantTypeChanger<String>::change(r_ret); *VariantGetInternalPtr<String>::get_ptr(r_ret) = do_mod(*VariantGetInternalPtr<String>::get_ptr(left), *VariantGetInternalPtr<Array>::get_ptr(right), nullptr); } -#ifdef PTRCALL_ENABLED static void ptr_evaluate(const void *left, const void *right, void *r_ret) { PtrToArg<String>::encode(do_mod(PtrToArg<String>::convert(left), PtrToArg<Array>::convert(right), nullptr), r_ret); } -#endif static Variant::Type get_return_type() { return Variant::STRING; } }; @@ -876,16 +795,13 @@ public: *r_ret = do_mod(a, p_right.get_validated_object(), &r_valid); r_valid = true; } - static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { VariantTypeChanger<String>::change(r_ret); *VariantGetInternalPtr<String>::get_ptr(r_ret) = do_mod(*VariantGetInternalPtr<String>::get_ptr(left), right->get_validated_object(), nullptr); } -#ifdef PTRCALL_ENABLED static void ptr_evaluate(const void *left, const void *right, void *r_ret) { PtrToArg<String>::encode(do_mod(PtrToArg<String>::convert(left), PtrToArg<Object *>::convert(right), nullptr), r_ret); } -#endif static Variant::Type get_return_type() { return Variant::STRING; } }; @@ -906,16 +822,13 @@ public: *r_ret = do_mod(a, *VariantGetInternalPtr<T>::get_ptr(&p_right), &r_valid); r_valid = true; } - static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { VariantTypeChanger<String>::change(r_ret); *VariantGetInternalPtr<String>::get_ptr(r_ret) = do_mod(*VariantGetInternalPtr<String>::get_ptr(left), *VariantGetInternalPtr<T>::get_ptr(right), nullptr); } -#ifdef PTRCALL_ENABLED static void ptr_evaluate(const void *left, const void *right, void *r_ret) { PtrToArg<String>::encode(do_mod(PtrToArg<String>::convert(left), PtrToArg<T>::convert(right), nullptr), r_ret); } -#endif static Variant::Type get_return_type() { return Variant::STRING; } }; @@ -926,16 +839,13 @@ public: *r_ret = true; r_valid = true; } - static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { VariantTypeChanger<bool>::change(r_ret); *VariantGetInternalPtr<bool>::get_ptr(r_ret) = true; } -#ifdef PTRCALL_ENABLED static void ptr_evaluate(const void *left, const void *right, void *r_ret) { PtrToArg<bool>::encode(true, r_ret); } -#endif static Variant::Type get_return_type() { return Variant::BOOL; } }; @@ -946,16 +856,13 @@ public: *r_ret = false; r_valid = true; } - static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { VariantTypeChanger<bool>::change(r_ret); *VariantGetInternalPtr<bool>::get_ptr(r_ret) = false; } -#ifdef PTRCALL_ENABLED static void ptr_evaluate(const void *left, const void *right, void *r_ret) { PtrToArg<bool>::encode(false, r_ret); } -#endif static Variant::Type get_return_type() { return Variant::BOOL; } }; @@ -964,9 +871,11 @@ public: _FORCE_INLINE_ static bool _operate_or(bool p_left, bool p_right) { return p_left || p_right; } + _FORCE_INLINE_ static bool _operate_and(bool p_left, bool p_right) { return p_left && p_right; } + _FORCE_INLINE_ static bool _operate_xor(bool p_left, bool p_right) { return (p_left || p_right) && !(p_left && p_right); } @@ -991,29 +900,6 @@ _FORCE_INLINE_ static bool _operate_get_object(const Variant *p_ptr) { return p_ptr->get_validated_object() != nullptr; } -#ifndef PTRCALL_ENABLED - -#define OP_EVALUATOR(m_class_name, m_left, m_right, m_op) \ - class m_class_name { \ - public: \ - static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { \ - *r_ret = m_op(_operate_get_##m_left(&p_left), _operate_get_##m_right(&p_right)); \ - r_valid = true; \ - } \ - \ - static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { \ - VariantTypeChanger<bool>::change(r_ret); \ - *VariantGetInternalPtr<bool>::get_ptr(r_ret) = m_op(_operate_get_##m_left(left), _operate_get_##m_right(right)); \ - } \ - \ - static Variant::Type \ - get_return_type() { \ - return Variant::BOOL; \ - } \ - }; - -#else - _FORCE_INLINE_ static bool _operate_get_ptr_nil(const void *p_ptr) { return false; } @@ -1056,11 +942,9 @@ _FORCE_INLINE_ static bool _operate_get_ptr_object(const void *p_ptr) { } \ }; -#endif - // OR -//nil +// nil OP_EVALUATOR(OperatorEvaluatorNilXBoolOr, nil, bool, _operate_or) OP_EVALUATOR(OperatorEvaluatorBoolXNilOr, bool, nil, _operate_or) @@ -1073,7 +957,7 @@ OP_EVALUATOR(OperatorEvaluatorFloatXNilOr, float, nil, _operate_or) OP_EVALUATOR(OperatorEvaluatorObjectXNilOr, object, nil, _operate_or) OP_EVALUATOR(OperatorEvaluatorNilXObjectOr, nil, object, _operate_or) -//bool +// bool OP_EVALUATOR(OperatorEvaluatorBoolXBoolOr, bool, bool, _operate_or) OP_EVALUATOR(OperatorEvaluatorBoolXIntOr, bool, int, _operate_or) @@ -1085,8 +969,7 @@ OP_EVALUATOR(OperatorEvaluatorFloatXBoolOr, float, bool, _operate_or) OP_EVALUATOR(OperatorEvaluatorBoolXObjectOr, bool, object, _operate_or) OP_EVALUATOR(OperatorEvaluatorObjectXBoolOr, object, bool, _operate_or) -//int - +// int OP_EVALUATOR(OperatorEvaluatorIntXIntOr, int, int, _operate_or) OP_EVALUATOR(OperatorEvaluatorIntXFloatOr, int, float, _operate_or) @@ -1095,20 +978,18 @@ OP_EVALUATOR(OperatorEvaluatorFloatXIntOr, float, int, _operate_or) OP_EVALUATOR(OperatorEvaluatorIntXObjectOr, int, object, _operate_or) OP_EVALUATOR(OperatorEvaluatorObjectXIntOr, object, int, _operate_or) -//float - +// float OP_EVALUATOR(OperatorEvaluatorFloatXFloatOr, float, float, _operate_or) OP_EVALUATOR(OperatorEvaluatorFloatXObjectOr, float, object, _operate_or) OP_EVALUATOR(OperatorEvaluatorObjectXFloatOr, object, float, _operate_or) -//object - +// object OP_EVALUATOR(OperatorEvaluatorObjectXObjectOr, object, object, _operate_or) // AND -//nil +// nil OP_EVALUATOR(OperatorEvaluatorNilXBoolAnd, nil, bool, _operate_and) OP_EVALUATOR(OperatorEvaluatorBoolXNilAnd, bool, nil, _operate_and) @@ -1121,7 +1002,7 @@ OP_EVALUATOR(OperatorEvaluatorFloatXNilAnd, float, nil, _operate_and) OP_EVALUATOR(OperatorEvaluatorObjectXNilAnd, object, nil, _operate_and) OP_EVALUATOR(OperatorEvaluatorNilXObjectAnd, nil, object, _operate_and) -//bool +// bool OP_EVALUATOR(OperatorEvaluatorBoolXBoolAnd, bool, bool, _operate_and) OP_EVALUATOR(OperatorEvaluatorBoolXIntAnd, bool, int, _operate_and) @@ -1133,8 +1014,7 @@ OP_EVALUATOR(OperatorEvaluatorFloatXBoolAnd, float, bool, _operate_and) OP_EVALUATOR(OperatorEvaluatorBoolXObjectAnd, bool, object, _operate_and) OP_EVALUATOR(OperatorEvaluatorObjectXBoolAnd, object, bool, _operate_and) -//int - +// int OP_EVALUATOR(OperatorEvaluatorIntXIntAnd, int, int, _operate_and) OP_EVALUATOR(OperatorEvaluatorIntXFloatAnd, int, float, _operate_and) @@ -1143,20 +1023,18 @@ OP_EVALUATOR(OperatorEvaluatorFloatXIntAnd, float, int, _operate_and) OP_EVALUATOR(OperatorEvaluatorIntXObjectAnd, int, object, _operate_and) OP_EVALUATOR(OperatorEvaluatorObjectXIntAnd, object, int, _operate_and) -//float - +// float OP_EVALUATOR(OperatorEvaluatorFloatXFloatAnd, float, float, _operate_and) OP_EVALUATOR(OperatorEvaluatorFloatXObjectAnd, float, object, _operate_and) OP_EVALUATOR(OperatorEvaluatorObjectXFloatAnd, object, float, _operate_and) -//object - +// object OP_EVALUATOR(OperatorEvaluatorObjectXObjectAnd, object, object, _operate_and) // XOR -//nil +// nil OP_EVALUATOR(OperatorEvaluatorNilXBoolXor, nil, bool, _operate_xor) OP_EVALUATOR(OperatorEvaluatorBoolXNilXor, bool, nil, _operate_xor) @@ -1169,7 +1047,7 @@ OP_EVALUATOR(OperatorEvaluatorFloatXNilXor, float, nil, _operate_xor) OP_EVALUATOR(OperatorEvaluatorObjectXNilXor, object, nil, _operate_xor) OP_EVALUATOR(OperatorEvaluatorNilXObjectXor, nil, object, _operate_xor) -//bool +// bool OP_EVALUATOR(OperatorEvaluatorBoolXBoolXor, bool, bool, _operate_xor) OP_EVALUATOR(OperatorEvaluatorBoolXIntXor, bool, int, _operate_xor) @@ -1181,8 +1059,7 @@ OP_EVALUATOR(OperatorEvaluatorFloatXBoolXor, float, bool, _operate_xor) OP_EVALUATOR(OperatorEvaluatorBoolXObjectXor, bool, object, _operate_xor) OP_EVALUATOR(OperatorEvaluatorObjectXBoolXor, object, bool, _operate_xor) -//int - +// int OP_EVALUATOR(OperatorEvaluatorIntXIntXor, int, int, _operate_xor) OP_EVALUATOR(OperatorEvaluatorIntXFloatXor, int, float, _operate_xor) @@ -1191,15 +1068,13 @@ OP_EVALUATOR(OperatorEvaluatorFloatXIntXor, float, int, _operate_xor) OP_EVALUATOR(OperatorEvaluatorIntXObjectXor, int, object, _operate_xor) OP_EVALUATOR(OperatorEvaluatorObjectXIntXor, object, int, _operate_xor) -//float - +// float OP_EVALUATOR(OperatorEvaluatorFloatXFloatXor, float, float, _operate_xor) OP_EVALUATOR(OperatorEvaluatorFloatXObjectXor, float, object, _operate_xor) OP_EVALUATOR(OperatorEvaluatorObjectXFloatXor, object, float, _operate_xor) -//object - +// object OP_EVALUATOR(OperatorEvaluatorObjectXObjectXor, object, object, _operate_xor) class OperatorEvaluatorNotBool { @@ -1208,17 +1083,13 @@ public: *r_ret = !*VariantGetInternalPtr<bool>::get_ptr(&p_left); r_valid = true; } - static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { VariantTypeChanger<bool>::change(r_ret); *VariantGetInternalPtr<bool>::get_ptr(r_ret) = !*VariantGetInternalPtr<bool>::get_ptr(left); } -#ifdef PTRCALL_ENABLED static void ptr_evaluate(const void *left, const void *right, void *r_ret) { PtrToArg<bool>::encode(!PtrToArg<bool>::convert(left), r_ret); } -#endif - static Variant::Type get_return_type() { return Variant::BOOL; } }; @@ -1228,17 +1099,13 @@ public: *r_ret = !*VariantGetInternalPtr<int64_t>::get_ptr(&p_left); r_valid = true; } - static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { VariantTypeChanger<bool>::change(r_ret); *VariantGetInternalPtr<bool>::get_ptr(r_ret) = !*VariantGetInternalPtr<int64_t>::get_ptr(left); } -#ifdef PTRCALL_ENABLED static void ptr_evaluate(const void *left, const void *right, void *r_ret) { PtrToArg<bool>::encode(!PtrToArg<int64_t>::convert(left), r_ret); } -#endif - static Variant::Type get_return_type() { return Variant::BOOL; } }; @@ -1248,17 +1115,13 @@ public: *r_ret = !*VariantGetInternalPtr<double>::get_ptr(&p_left); r_valid = true; } - static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { VariantTypeChanger<bool>::change(r_ret); *VariantGetInternalPtr<bool>::get_ptr(r_ret) = !*VariantGetInternalPtr<double>::get_ptr(left); } -#ifdef PTRCALL_ENABLED static void ptr_evaluate(const void *left, const void *right, void *r_ret) { PtrToArg<bool>::encode(!PtrToArg<double>::convert(left), r_ret); } -#endif - static Variant::Type get_return_type() { return Variant::BOOL; } }; @@ -1268,17 +1131,13 @@ public: *r_ret = p_left.get_validated_object() == nullptr; r_valid = true; } - static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { VariantTypeChanger<bool>::change(r_ret); *VariantGetInternalPtr<bool>::get_ptr(r_ret) = left->get_validated_object() == nullptr; } -#ifdef PTRCALL_ENABLED static void ptr_evaluate(const void *left, const void *right, void *r_ret) { PtrToArg<bool>::encode(PtrToArg<Object *>::convert(left) == nullptr, r_ret); } -#endif - static Variant::Type get_return_type() { return Variant::BOOL; } }; @@ -1293,18 +1152,15 @@ public: *r_ret = str_b.find(str_a) != -1; r_valid = true; } - static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { const String &str_a = *VariantGetInternalPtr<String>::get_ptr(left); const String &str_b = *VariantGetInternalPtr<String>::get_ptr(right); VariantTypeChanger<bool>::change(r_ret); *VariantGetInternalPtr<bool>::get_ptr(r_ret) = str_b.find(str_a) != -1; } -#ifdef PTRCALL_ENABLED static void ptr_evaluate(const void *left, const void *right, void *r_ret) { PtrToArg<bool>::encode(PtrToArg<String>::convert(right).find(PtrToArg<String>::convert(left)) != -1, r_ret); } -#endif static Variant::Type get_return_type() { return Variant::BOOL; } }; @@ -1318,18 +1174,15 @@ public: *r_ret = b.find(a) != -1; r_valid = true; } - static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { const A &a = *VariantGetInternalPtr<A>::get_ptr(left); const B &b = *VariantGetInternalPtr<B>::get_ptr(right); VariantTypeChanger<bool>::change(r_ret); *VariantGetInternalPtr<bool>::get_ptr(r_ret) = b.find(a) != -1; } -#ifdef PTRCALL_ENABLED static void ptr_evaluate(const void *left, const void *right, void *r_ret) { PtrToArg<bool>::encode(PtrToArg<B>::convert(right).find(PtrToArg<A>::convert(left)) != -1, r_ret); } -#endif static Variant::Type get_return_type() { return Variant::BOOL; } }; @@ -1340,17 +1193,14 @@ public: *r_ret = b.find(Variant()) != -1; r_valid = true; } - static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { const Array &b = *VariantGetInternalPtr<Array>::get_ptr(right); VariantTypeChanger<bool>::change(r_ret); *VariantGetInternalPtr<bool>::get_ptr(r_ret) = b.find(Variant()) != -1; } -#ifdef PTRCALL_ENABLED static void ptr_evaluate(const void *left, const void *right, void *r_ret) { PtrToArg<bool>::encode(PtrToArg<Array>::convert(right).find(Variant()) != -1, r_ret); } -#endif static Variant::Type get_return_type() { return Variant::BOOL; } }; @@ -1361,17 +1211,14 @@ public: *r_ret = b.find(p_left) != -1; r_valid = true; } - static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { const Array &b = *VariantGetInternalPtr<Array>::get_ptr(right); VariantTypeChanger<bool>::change(r_ret); *VariantGetInternalPtr<bool>::get_ptr(r_ret) = b.find(*left) != -1; } -#ifdef PTRCALL_ENABLED static void ptr_evaluate(const void *left, const void *right, void *r_ret) { PtrToArg<bool>::encode(PtrToArg<Array>::convert(right).find(PtrToArg<Object *>::convert(left)) != -1, r_ret); } -#endif static Variant::Type get_return_type() { return Variant::BOOL; } }; @@ -1385,18 +1232,15 @@ public: *r_ret = b.has(a); r_valid = true; } - static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { const Dictionary &b = *VariantGetInternalPtr<Dictionary>::get_ptr(right); const A &a = *VariantGetInternalPtr<A>::get_ptr(left); VariantTypeChanger<bool>::change(r_ret); *VariantGetInternalPtr<bool>::get_ptr(r_ret) = b.has(a); } -#ifdef PTRCALL_ENABLED static void ptr_evaluate(const void *left, const void *right, void *r_ret) { PtrToArg<bool>::encode(PtrToArg<Dictionary>::convert(right).has(PtrToArg<A>::convert(left)), r_ret); } -#endif static Variant::Type get_return_type() { return Variant::BOOL; } }; @@ -1408,17 +1252,14 @@ public: *r_ret = b.has(Variant()); r_valid = true; } - static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { const Dictionary &b = *VariantGetInternalPtr<Dictionary>::get_ptr(right); VariantTypeChanger<bool>::change(r_ret); *VariantGetInternalPtr<bool>::get_ptr(r_ret) = b.has(Variant()); } -#ifdef PTRCALL_ENABLED static void ptr_evaluate(const void *left, const void *right, void *r_ret) { PtrToArg<bool>::encode(PtrToArg<Dictionary>::convert(right).has(Variant()), r_ret); } -#endif static Variant::Type get_return_type() { return Variant::BOOL; } }; @@ -1430,17 +1271,14 @@ public: *r_ret = b.has(p_left); r_valid = true; } - static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { const Dictionary &b = *VariantGetInternalPtr<Dictionary>::get_ptr(right); VariantTypeChanger<bool>::change(r_ret); *VariantGetInternalPtr<bool>::get_ptr(r_ret) = b.has(*left); } -#ifdef PTRCALL_ENABLED static void ptr_evaluate(const void *left, const void *right, void *r_ret) { PtrToArg<bool>::encode(PtrToArg<Dictionary>::convert(right).has(PtrToArg<Object *>::convert(left)), r_ret); } -#endif static Variant::Type get_return_type() { return Variant::BOOL; } }; @@ -1459,7 +1297,6 @@ public: b->get(a, &r_valid); *r_ret = r_valid; } - static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { Object *l = right->get_validated_object(); ERR_FAIL_COND(l == nullptr); @@ -1470,13 +1307,11 @@ public: VariantTypeChanger<bool>::change(r_ret); *VariantGetInternalPtr<bool>::get_ptr(r_ret) = valid; } -#ifdef PTRCALL_ENABLED static void ptr_evaluate(const void *left, const void *right, void *r_ret) { bool valid; PtrToArg<Object *>::convert(right)->get(PtrToArg<String>::convert(left), &valid); PtrToArg<bool>::encode(valid, r_ret); } -#endif static Variant::Type get_return_type() { return Variant::BOOL; } }; @@ -1495,7 +1330,6 @@ public: b->get(a, &r_valid); *r_ret = r_valid; } - static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { Object *l = right->get_validated_object(); ERR_FAIL_COND(l == nullptr); @@ -1506,13 +1340,11 @@ public: VariantTypeChanger<bool>::change(r_ret); *VariantGetInternalPtr<bool>::get_ptr(r_ret) = valid; } -#ifdef PTRCALL_ENABLED static void ptr_evaluate(const void *left, const void *right, void *r_ret) { bool valid; PtrToArg<Object *>::convert(right)->get(PtrToArg<StringName>::convert(left), &valid); PtrToArg<bool>::encode(valid, r_ret); } -#endif static Variant::Type get_return_type() { return Variant::BOOL; } }; @@ -1521,27 +1353,21 @@ typedef void (*VariantEvaluatorFunction)(const Variant &p_left, const Variant &p static Variant::Type operator_return_type_table[Variant::OP_MAX][Variant::VARIANT_MAX][Variant::VARIANT_MAX]; static VariantEvaluatorFunction operator_evaluator_table[Variant::OP_MAX][Variant::VARIANT_MAX][Variant::VARIANT_MAX]; static Variant::ValidatedOperatorEvaluator validated_operator_evaluator_table[Variant::OP_MAX][Variant::VARIANT_MAX][Variant::VARIANT_MAX]; -#ifdef PTRCALL_ENABLED static Variant::PTROperatorEvaluator ptr_operator_evaluator_table[Variant::OP_MAX][Variant::VARIANT_MAX][Variant::VARIANT_MAX]; -#endif template <class T> void register_op(Variant::Operator p_op, Variant::Type p_type_a, Variant::Type p_type_b) { operator_return_type_table[p_op][p_type_a][p_type_b] = T::get_return_type(); operator_evaluator_table[p_op][p_type_a][p_type_b] = T::evaluate; validated_operator_evaluator_table[p_op][p_type_a][p_type_b] = T::validated_evaluate; -#ifdef PTRCALL_ENABLED ptr_operator_evaluator_table[p_op][p_type_a][p_type_b] = T::ptr_evaluate; -#endif } void Variant::_register_variant_operators() { zeromem(operator_return_type_table, sizeof(operator_return_type_table)); zeromem(operator_evaluator_table, sizeof(operator_evaluator_table)); zeromem(validated_operator_evaluator_table, sizeof(validated_operator_evaluator_table)); -#ifdef PTRCALL_ENABLED zeromem(ptr_operator_evaluator_table, sizeof(ptr_operator_evaluator_table)); -#endif register_op<OperatorEvaluatorAdd<int64_t, int64_t, int64_t>>(Variant::OP_ADD, Variant::INT, Variant::INT); register_op<OperatorEvaluatorAdd<double, int64_t, double>>(Variant::OP_ADD, Variant::INT, Variant::FLOAT); @@ -1896,7 +1722,7 @@ void Variant::_register_variant_operators() { register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_OR, Variant::NIL, Variant::NIL>>(Variant::OP_OR, Variant::NIL, Variant::NIL); - //OR + // OR register_op<OperatorEvaluatorNilXBoolOr>(Variant::OP_OR, Variant::NIL, Variant::BOOL); register_op<OperatorEvaluatorBoolXNilOr>(Variant::OP_OR, Variant::BOOL, Variant::NIL); register_op<OperatorEvaluatorNilXIntOr>(Variant::OP_OR, Variant::NIL, Variant::INT); @@ -1924,7 +1750,8 @@ void Variant::_register_variant_operators() { register_op<OperatorEvaluatorFloatXObjectOr>(Variant::OP_OR, Variant::FLOAT, Variant::OBJECT); register_op<OperatorEvaluatorObjectXFloatOr>(Variant::OP_OR, Variant::OBJECT, Variant::FLOAT); register_op<OperatorEvaluatorObjectXObjectOr>(Variant::OP_OR, Variant::OBJECT, Variant::OBJECT); - //AND + + // AND register_op<OperatorEvaluatorNilXBoolAnd>(Variant::OP_AND, Variant::NIL, Variant::BOOL); register_op<OperatorEvaluatorBoolXNilAnd>(Variant::OP_AND, Variant::BOOL, Variant::NIL); register_op<OperatorEvaluatorNilXIntAnd>(Variant::OP_AND, Variant::NIL, Variant::INT); @@ -1952,7 +1779,8 @@ void Variant::_register_variant_operators() { register_op<OperatorEvaluatorFloatXObjectAnd>(Variant::OP_AND, Variant::FLOAT, Variant::OBJECT); register_op<OperatorEvaluatorObjectXFloatAnd>(Variant::OP_AND, Variant::OBJECT, Variant::FLOAT); register_op<OperatorEvaluatorObjectXObjectAnd>(Variant::OP_AND, Variant::OBJECT, Variant::OBJECT); - //XOR + + // XOR register_op<OperatorEvaluatorNilXBoolXor>(Variant::OP_XOR, Variant::NIL, Variant::BOOL); register_op<OperatorEvaluatorBoolXNilXor>(Variant::OP_XOR, Variant::BOOL, Variant::NIL); register_op<OperatorEvaluatorNilXIntXor>(Variant::OP_XOR, Variant::NIL, Variant::INT); @@ -2124,7 +1952,7 @@ Variant::ValidatedOperatorEvaluator Variant::get_validated_operator_evaluator(Op ERR_FAIL_INDEX_V(p_type_b, Variant::VARIANT_MAX, nullptr); return validated_operator_evaluator_table[p_operator][p_type_a][p_type_b]; } -#ifdef PTRCALL_ENABLED + Variant::PTROperatorEvaluator Variant::get_ptr_operator_evaluator(Operator p_operator, Type p_type_a, Type p_type_b) { ERR_FAIL_INDEX_V(p_operator, Variant::OP_MAX, nullptr); ERR_FAIL_INDEX_V(p_type_a, Variant::VARIANT_MAX, nullptr); @@ -2132,8 +1960,6 @@ Variant::PTROperatorEvaluator Variant::get_ptr_operator_evaluator(Operator p_ope return ptr_operator_evaluator_table[p_operator][p_type_a][p_type_b]; } -#endif - static const char *_op_names[Variant::OP_MAX] = { "==", "!=", diff --git a/core/variant/variant_utility.cpp b/core/variant/variant_utility.cpp index 70edcd48c2..d54e223a99 100644 --- a/core/variant/variant_utility.cpp +++ b/core/variant/variant_utility.cpp @@ -537,7 +537,7 @@ struct VariantUtilityFunctions { str += p_args[i]->operator String(); } - print_error(str); + print_line(str); r_error.error = Callable::CallError::CALL_OK; } @@ -554,7 +554,7 @@ struct VariantUtilityFunctions { str += p_args[i]->operator String(); } - print_error(str); + print_line(str); r_error.error = Callable::CallError::CALL_OK; } diff --git a/doc/classes/EditorNode3DGizmoPlugin.xml b/doc/classes/EditorNode3DGizmoPlugin.xml index adaaed4f1c..322cff4e43 100644 --- a/doc/classes/EditorNode3DGizmoPlugin.xml +++ b/doc/classes/EditorNode3DGizmoPlugin.xml @@ -125,7 +125,7 @@ </return> <argument index="0" name="name" type="String"> </argument> - <argument index="1" name="gizmo" type="EditorNode3DGizmo"> + <argument index="1" name="gizmo" type="EditorNode3DGizmo" default="null"> </argument> <description> Gets material from the internal list of materials. If an [EditorNode3DGizmo] is provided, it will try to get the corresponding variant (selected and/or editable). diff --git a/doc/classes/File.xml b/doc/classes/File.xml index ada57a8114..2f7ac551cf 100644 --- a/doc/classes/File.xml +++ b/doc/classes/File.xml @@ -6,7 +6,8 @@ <description> File type. This is used to permanently store data into the user device's file system and to read from it. This can be used to store game save data or player configuration files, for example. Here's a sample on how to write and read from a file: - [codeblock] + [codeblocks] + [gdscript] func save(content): var file = File.new() file.open("user://save_game.dat", File.WRITE) @@ -19,7 +20,26 @@ var content = file.get_as_text() file.close() return content - [/codeblock] + [/gdscript] + [csharp] + public void Save(string content) + { + var file = new File(); + file.Open("user://save_game.dat", File.ModeFlags.Write); + file.StoreString(content); + file.Close(); + } + + public string Load() + { + var file = new File(); + file.Open("user://save_game.dat", File.ModeFlags.Read); + string content = file.GetAsText(); + file.Close(); + return content; + } + [/csharp] + [/codeblocks] In the example above, the file will be saved in the user data folder as specified in the [url=https://docs.godotengine.org/en/latest/tutorials/io/data_paths.html]Data paths[/url] documentation. [b]Note:[/b] To access project resources once exported, it is recommended to use [ResourceLoader] instead of the [File] API, as some files are converted to engine-specific formats and their original source files might not be present in the exported PCK package. </description> @@ -303,7 +323,8 @@ Stores an integer as 16 bits in the file. [b]Note:[/b] The [code]value[/code] should lie in the interval [code][0, 2^16 - 1][/code]. Any other value will overflow and wrap around. To store a signed integer, use [method store_64] or store a signed integer from the interval [code][-2^15, 2^15 - 1][/code] (i.e. keeping one bit for the signedness) and compute its sign manually when reading. For example: - [codeblock] + [codeblocks] + [gdscript] const MAX_15B = 1 << 15 const MAX_16B = 1 << 16 @@ -320,7 +341,22 @@ var read2 = f.get_16() # 121 var converted1 = unsigned16_to_signed(read1) # -42 var converted2 = unsigned16_to_signed(read2) # 121 - [/codeblock] + [/gdscript] + [csharp] + public override void _Ready() + { + var f = new File(); + f.Open("user://file.dat", File.ModeFlags.WriteRead); + f.Store16(unchecked((ushort)-42)); // This wraps around and stores 65494 (2^16 - 42). + f.Store16(121); // In bounds, will store 121. + f.Seek(0); // Go back to start to read the stored value. + ushort read1 = f.Get16(); // 65494 + ushort read2 = f.Get16(); // 121 + short converted1 = BitConverter.ToInt16(BitConverter.GetBytes(read1), 0); // -42 + short converted2 = BitConverter.ToInt16(BitConverter.GetBytes(read2), 0); // 121 + } + [/csharp] + [/codeblocks] </description> </method> <method name="store_32"> diff --git a/doc/classes/Geometry2D.xml b/doc/classes/Geometry2D.xml index a6bcc1301b..4ff54d15ce 100644 --- a/doc/classes/Geometry2D.xml +++ b/doc/classes/Geometry2D.xml @@ -201,12 +201,21 @@ Each polygon's vertices will be rounded as determined by [code]join_type[/code], see [enum PolyJoinType]. The operation may result in an outer polygon (boundary) and inner polygon (hole) produced which could be distinguished by calling [method is_polygon_clockwise]. [b]Note:[/b] To translate the polygon's vertices specifically, multiply them to a [Transform2D]: - [codeblock] + [codeblocks] + [gdscript] var polygon = PackedVector2Array([Vector2(0, 0), Vector2(100, 0), Vector2(100, 100), Vector2(0, 100)]) var offset = Vector2(50, 50) polygon = Transform2D(0, offset) * polygon print(polygon) # prints [Vector2(50, 50), Vector2(150, 50), Vector2(150, 150), Vector2(50, 150)] - [/codeblock] + [/gdscript] + [csharp] + var polygon = new Vector2[] { new Vector2(0, 0), new Vector2(100, 0), new Vector2(100, 100), new Vector2(0, 100) }; + var offset = new Vector2(50, 50); + // TODO: This code is not valid right now. Ping @aaronfranke about it before Godot 4.0 is out. + //polygon = (Vector2[]) new Transform2D(0, offset).Xform(polygon); + //GD.Print(polygon); // prints [Vector2(50, 50), Vector2(150, 50), Vector2(150, 150), Vector2(50, 150)] + [/csharp] + [/codeblocks] </description> </method> <method name="offset_polyline"> diff --git a/doc/classes/HTTPClient.xml b/doc/classes/HTTPClient.xml index ec8ca7456a..b6594aac39 100644 --- a/doc/classes/HTTPClient.xml +++ b/doc/classes/HTTPClient.xml @@ -112,17 +112,31 @@ </argument> <description> Generates a GET/POST application/x-www-form-urlencoded style query string from a provided dictionary, e.g.: - [codeblock] + [codeblocks] + [gdscript] var fields = {"username": "user", "password": "pass"} var query_string = http_client.query_string_from_dict(fields) # Returns "username=user&password=pass" - [/codeblock] + [/gdscript] + [csharp] + var fields = new Godot.Collections.Dictionary { { "username", "user" }, { "password", "pass" } }; + string queryString = new HTTPClient().QueryStringFromDict(fields); + // Returns "username=user&password=pass" + [/csharp] + [/codeblocks] Furthermore, if a key has a [code]null[/code] value, only the key itself is added, without equal sign and value. If the value is an array, for each value in it a pair with the same key is added. - [codeblock] + [codeblocks] + [gdscript] var fields = {"single": 123, "not_valued": null, "multiple": [22, 33, 44]} var query_string = http_client.query_string_from_dict(fields) # Returns "single=123&not_valued&multiple=22&multiple=33&multiple=44" - [/codeblock] + [/gdscript] + [csharp] + var fields = new Godot.Collections.Dictionary{{"single", 123}, {"notValued", null}, {"multiple", new Godot.Collections.Array{22, 33, 44}}}; + string queryString = new HTTPClient().QueryStringFromDict(fields); + // Returns "single=123&not_valued&multiple=22&multiple=33&multiple=44" + [/csharp] + [/codeblocks] </description> </method> <method name="read_response_body_chunk"> @@ -147,12 +161,20 @@ Sends a request to the connected host. The URL parameter is just the part after the host, so for [code]http://somehost.com/index.php[/code], it is [code]index.php[/code]. Headers are HTTP request headers. For available HTTP methods, see [enum Method]. To create a POST request with query strings to push to the server, do: - [codeblock] + [codeblocks] + [gdscript] var fields = {"username" : "user", "password" : "pass"} var query_string = http_client.query_string_from_dict(fields) var headers = ["Content-Type: application/x-www-form-urlencoded", "Content-Length: " + str(query_string.length())] var result = http_client.request(http_client.METHOD_POST, "index.php", headers, query_string) - [/codeblock] + [/gdscript] + [csharp] + var fields = new Godot.Collections.Dictionary { { "username", "user" }, { "password", "pass" } }; + string queryString = new HTTPClient().QueryStringFromDict(fields); + string[] headers = {"Content-Type: application/x-www-form-urlencoded", "Content-Length: " + queryString.Length}; + var result = new HTTPClient().Request(HTTPClient.Method.Post, "index.php", headers, queryString); + [/csharp] + [/codeblocks] [b]Note:[/b] The [code]request_data[/code] parameter is ignored if [code]method[/code] is [constant HTTPClient.METHOD_GET]. This is because GET methods can't contain request data. As a workaround, you can pass request data as a query string in the URL. See [method String.http_escape] for an example. </description> </method> diff --git a/doc/classes/HTTPRequest.xml b/doc/classes/HTTPRequest.xml index 6eae881ffe..f2ab93033a 100644 --- a/doc/classes/HTTPRequest.xml +++ b/doc/classes/HTTPRequest.xml @@ -7,7 +7,8 @@ A node with the ability to send HTTP requests. Uses [HTTPClient] internally. Can be used to make HTTP requests, i.e. download or upload files or web content via HTTP. [b]Example of contacting a REST API and printing one of its returned fields:[/b] - [codeblock] + [codeblocks] + [gdscript] func _ready(): # Create an HTTP request node and connect its completion signal. var http_request = HTTPRequest.new() @@ -34,9 +35,48 @@ # Will print the user agent string used by the HTTPRequest node (as recognized by httpbin.org). print(response.headers["User-Agent"]) - [/codeblock] + [/gdscript] + [csharp] + public override void _Ready() + { + // Create an HTTP request node and connect its completion signal. + var httpRequest = new HTTPRequest(); + AddChild(httpRequest); + httpRequest.Connect("request_completed", this, nameof(HttpRequestCompleted)); + + // Perform a GET request. The URL below returns JSON as of writing. + Error error = httpRequest.Request("https://httpbin.org/get"); + if (error != Error.Ok) + { + GD.PushError("An error occurred in the HTTP request."); + } + + // Perform a POST request. The URL below returns JSON as of writing. + // Note: Don't make simultaneous requests using a single HTTPRequest node. + // The snippet below is provided for reference only. + string[] body = { "name", "Godette" }; + // GDScript to_json is non existent, so we use JSON.Print() here. + error = httpRequest.Request("https://httpbin.org/post", null, true, HTTPClient.Method.Post, JSON.Print(body)); + if (error != Error.Ok) + { + GD.PushError("An error occurred in the HTTP request."); + } + } + + + // Called when the HTTP request is completed. + private void HttpRequestCompleted(int result, int response_code, string[] headers, byte[] body) + { + // GDScript parse_json is non existent so we have to use JSON.parse, which has a slightly different syntax. + var response = JSON.Parse(body.GetStringFromUTF8()).Result as Godot.Collections.Dictionary; + // Will print the user agent string used by the HTTPRequest node (as recognized by httpbin.org). + GD.Print((response["headers"] as Godot.Collections.Dictionary)["User-Agent"]); + } + [/csharp] + [/codeblocks] [b]Example of loading and displaying an image using HTTPRequest:[/b] - [codeblock] + [codeblocks] + [gdscript] func _ready(): # Create an HTTP request node and connect its completion signal. var http_request = HTTPRequest.new() @@ -51,6 +91,9 @@ # Called when the HTTP request is completed. func _http_request_completed(result, response_code, headers, body): + if result != HTTPRequest.RESULT_SUCCESS: + push_error("Image couldn't be downloaded. Try a different image.") + var image = Image.new() var error = image.load_png_from_buffer(body) if error != OK: @@ -63,7 +106,48 @@ var texture_rect = TextureRect.new() add_child(texture_rect) texture_rect.texture = texture - [/codeblock] + [/gdscript] + [csharp] + public override void _Ready() + { + // Create an HTTP request node and connect its completion signal. + var httpRequest = new HTTPRequest(); + AddChild(httpRequest); + httpRequest.Connect("request_completed", this, nameof(HttpRequestCompleted)); + + // Perform the HTTP request. The URL below returns a PNG image as of writing. + Error error = httpRequest.Request("https://via.placeholder.com/512"); + if (error != Error.Ok) + { + GD.PushError("An error occurred in the HTTP request."); + } + } + + + // Called when the HTTP request is completed. + private void HttpRequestCompleted(int result, int response_code, string[] headers, byte[] body) + { + if (result != (int)HTTPRequest.Result.Success) + { + GD.PushError("Image couldn't be downloaded. Try a different image."); + } + var image = new Image(); + Error error = image.LoadPngFromBuffer(body); + if (error != Error.Ok) + { + GD.PushError("Couldn't load the image."); + } + + var texture = new ImageTexture(); + texture.CreateFromImage(image); + + // Display the image in a TextureRect node. + var textureRect = new TextureRect(); + AddChild(textureRect); + textureRect.Texture = texture; + } + [/csharp] + [/codeblocks] [b]Gzipped response bodies[/b]: HTTPRequest will automatically handle decompression of response bodies. A [code]Accept-Encoding[/code] header will be automatically added to each of your requests, unless one is already specified. Any response with a [code]Content-Encoding: gzip[/code] header will automatically be decompressed and delivered to you as uncompressed bytes. [b]Note:[/b] When performing HTTP requests from a project exported to HTML5, keep in mind the remote server may not allow requests from foreign origins due to [url=https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS]CORS[/url]. If you host the server in question, you should modify its backend to allow requests from foreign origins by adding the [code]Access-Control-Allow-Origin: *[/code] HTTP header. diff --git a/doc/classes/HashingContext.xml b/doc/classes/HashingContext.xml index f8152c813e..e020293d76 100644 --- a/doc/classes/HashingContext.xml +++ b/doc/classes/HashingContext.xml @@ -6,8 +6,9 @@ <description> The HashingContext class provides an interface for computing cryptographic hashes over multiple iterations. This is useful for example when computing hashes of big files (so you don't have to load them all in memory), network streams, and data streams in general (so you don't have to hold buffers). The [enum HashType] enum shows the supported hashing algorithms. - [codeblock] - const CHUNK_SIZE = 1024 + [codeblocks] + [gdscript] + const CHUNK_SIZE = 102 func hash_file(path): var ctx = HashingContext.new() @@ -26,7 +27,36 @@ var res = ctx.finish() # Print the result as hex string and array. printt(res.hex_encode(), Array(res)) - [/codeblock] + [/gdscript] + [csharp] + public const int ChunkSize = 1024; + + public void HashFile(string path) + { + var ctx = new HashingContext(); + var file = new File(); + // Start a SHA-256 context. + ctx.Start(HashingContext.HashType.Sha256); + // Check that file exists. + if (!file.FileExists(path)) + { + return; + } + // Open the file to hash. + file.Open(path, File.ModeFlags.Read); + // Update the context after reading each chunk. + while (!file.EofReached()) + { + ctx.Update(file.GetBuffer(ChunkSize)); + } + // Get the computed hash. + byte[] res = ctx.Finish(); + // Print the result as hex string and array. + + GD.PrintT(res.HexEncode(), res); + } + [/csharp] + [/codeblocks] [b]Note:[/b] Not available in HTML5 exports. </description> <tutorials> diff --git a/doc/classes/Input.xml b/doc/classes/Input.xml index 2e619802e3..5d1d763ae3 100644 --- a/doc/classes/Input.xml +++ b/doc/classes/Input.xml @@ -299,12 +299,20 @@ <description> Feeds an [InputEvent] to the game. Can be used to artificially trigger input events from code. Also generates [method Node._input] calls. Example: - [codeblock] - var a = InputEventAction.new() - a.action = "ui_cancel" - a.pressed = true - Input.parse_input_event(a) - [/codeblock] + [codeblocks] + [gdscript] + var cancel_event = InputEventAction.new() + cancel_event.action = "ui_cancel" + cancel_event.pressed = true + Input.parse_input_event(cancel_event) + [/gdscript] + [csharp] + var cancelEvent = new InputEventAction(); + cancelEvent.Action = "ui_cancel"; + cancelEvent.Pressed = true; + Input.ParseInputEvent(cancelEvent); + [/csharp] + [/codeblocks] </description> </method> <method name="remove_joy_mapping"> diff --git a/doc/classes/ItemList.xml b/doc/classes/ItemList.xml index 25420bd77b..fd8bfb4ece 100644 --- a/doc/classes/ItemList.xml +++ b/doc/classes/ItemList.xml @@ -247,11 +247,16 @@ <argument index="1" name="custom_bg_color" type="Color"> </argument> <description> - Sets the background color of the item specified by [code]idx[/code] index to the specified [Color]. - [codeblock] - var some_string = "Some text" - some_string.set_item_custom_bg_color(0,Color(1, 0, 0, 1) # This will set the background color of the first item of the control to red. - [/codeblock] + [codeblocks] + [gdscript] + var itemList = ItemList.new() + some_string.set_item_custom_bg_color(0, Color.red) # This will set the background color of the first item of the control to red. + [/gdscript] + [csharp] + var itemList = new ItemList(); + itemList.SetItemCustomBgColor(0, Colors.Red); // This will set the background color of the first item of the control to red. + [/csharp] + [/codeblocks] </description> </method> <method name="set_item_custom_fg_color"> @@ -263,10 +268,16 @@ </argument> <description> Sets the foreground color of the item specified by [code]idx[/code] index to the specified [Color]. - [codeblock] - var some_string = "Some text" - some_string.set_item_custom_fg_color(0,Color(1, 0, 0, 1) # This will set the foreground color of the first item of the control to red. - [/codeblock] + [codeblocks] + [gdscript] + var item_list = ItemList.new() + item_list.set_item_custom_fg_color(0, Color.red) # This will set the foreground color of the first item of the control to red. + [/gdscript] + [csharp] + var itemList = new ItemList(); + itemList.SetItemCustomFgColor(0, Colors.Red); // This will set the foreground color of the first item of the control to red. + [/csharp] + [/codeblocks] </description> </method> <method name="set_item_disabled"> diff --git a/doc/classes/JSONParseResult.xml b/doc/classes/JSONParseResult.xml index 4dbceb35e9..991ebcd7a0 100644 --- a/doc/classes/JSONParseResult.xml +++ b/doc/classes/JSONParseResult.xml @@ -24,13 +24,26 @@ A [Variant] containing the parsed JSON. Use [method @GDScript.typeof] or the [code]is[/code] keyword to check if it is what you expect. For example, if the JSON source starts with curly braces ([code]{}[/code]), a [Dictionary] will be returned. If the JSON source starts with brackets ([code][][/code]), an [Array] will be returned. [b]Note:[/b] The JSON specification does not define integer or float types, but only a [i]number[/i] type. Therefore, parsing a JSON text will convert all numerical values to [float] types. [b]Note:[/b] JSON objects do not preserve key order like Godot dictionaries, thus, you should not rely on keys being in a certain order if a dictionary is constructed from JSON. In contrast, JSON arrays retain the order of their elements: - [codeblock] + [codeblocks] + [gdscript] var p = JSON.parse('["hello", "world", "!"]') if typeof(p.result) == TYPE_ARRAY: print(p.result[0]) # Prints "hello" else: push_error("Unexpected results.") - [/codeblock] + [/gdscript] + [csharp] + JSONParseResult p = JSON.Parse("[\"hello\"], \"world\", \"!\"]"); + if (p.Result is Godot.Collections.Array) + { + GD.Print((p.Result as Godot.Collections.Array)[0]); // Prints "hello" + } + else + { + GD.PushError("Unexpected results."); + } + [/csharp] + [/codeblocks] </member> </members> <constants> diff --git a/doc/classes/KinematicBody2D.xml b/doc/classes/KinematicBody2D.xml index 425df00b6f..476b64a336 100644 --- a/doc/classes/KinematicBody2D.xml +++ b/doc/classes/KinematicBody2D.xml @@ -37,11 +37,20 @@ <description> Returns a [KinematicCollision2D], which contains information about a collision that occurred during the last call to [method move_and_slide] or [method move_and_slide_with_snap]. Since the body can collide several times in a single call to [method move_and_slide], you must specify the index of the collision in the range 0 to ([method get_slide_count] - 1). [b]Example usage:[/b] - [codeblock] + [codeblocks] + [gdscript] for i in get_slide_count(): var collision = get_slide_collision(i) print("Collided with: ", collision.collider.name) - [/codeblock] + [/gdscript] + [csharp] + for (int i = 0; i < GetSlideCount(); i++) + { + KinematicCollision2D collision = GetSlideCollision(i); + GD.Print("Collided with: ", (collision.Collider as Node).Name); + } + [/csharp] + [/codeblocks] </description> </method> <method name="get_slide_count" qualifiers="const"> diff --git a/doc/classes/LineEdit.xml b/doc/classes/LineEdit.xml index 5c2dffd538..b7211419e4 100644 --- a/doc/classes/LineEdit.xml +++ b/doc/classes/LineEdit.xml @@ -103,12 +103,20 @@ </argument> <description> Selects characters inside [LineEdit] between [code]from[/code] and [code]to[/code]. By default, [code]from[/code] is at the beginning and [code]to[/code] at the end. - [codeblock] + [codeblocks] + [gdscript] text = "Welcome" select() # Will select "Welcome". select(4) # Will select "ome". select(2, 5) # Will select "lco". - [/codeblock] + [/gdscript] + [csharp] + Text = "Welcome"; + Select(); // Will select "Welcome". + Select(4); // Will select "ome". + Select(2, 5); // Will select "lco". + [/csharp] + [/codeblocks] </description> </method> <method name="select_all"> diff --git a/doc/classes/int.xml b/doc/classes/int.xml index 5ac9f8405a..b0d0a4bd7b 100644 --- a/doc/classes/int.xml +++ b/doc/classes/int.xml @@ -7,18 +7,34 @@ Signed 64-bit integer type. It can take values in the interval [code][-2^63, 2^63 - 1][/code], i.e. [code][-9223372036854775808, 9223372036854775807][/code]. Exceeding those bounds will wrap around. [int] is a [Variant] type, and will thus be used when assigning an integer value to a [Variant]. It can also be enforced with the [code]: int[/code] type hint. - [codeblock] + [codeblocks] + [gdscript] var my_variant = 0 # int, value 0. my_variant += 4.2 # float, value 4.2. var my_int: int = 1 # int, value 1. my_int = 4.2 # int, value 4, the right value is implicitly cast to int. my_int = int("6.7") # int, value 6, the String is explicitly cast with int. - var max_int = 9223372036854775807 print(max_int) # 9223372036854775807, OK. max_int += 1 print(max_int) # -9223372036854775808, we overflowed and wrapped around. - [/codeblock] + [/gdscript] + [csharp] + int myInt = (int)"6.7".ToFloat(); // int, value 6, the String is explicitly cast with int. + // We have to use `long` here, because GDSript's `int` + // is 64 bits long while C#'s `int` is only 32 bits. + long maxInt = 9223372036854775807; + GD.Print(maxInt); // 9223372036854775807, OK. + maxInt++; + GD.Print(maxInt); // -9223372036854775808, we overflowed and wrapped around. + + // Alternatively, if we used C#'s 32-bit `int` type, the maximum value is much smaller: + int halfInt = 2147483647; + GD.Print(halfInt); // 2147483647, OK. + halfInt++; + GD.Print(halfInt); // -2147483648, we overflowed and wrapped around. + [/csharp] + [/codeblocks] </description> <tutorials> </tutorials> diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index fa7300c930..8420faa302 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -6847,7 +6847,7 @@ void EditorNode3DGizmoPlugin::_bind_methods() { ClassDB::bind_method(D_METHOD("create_handle_material", "name", "billboard", "texture"), &EditorNode3DGizmoPlugin::create_handle_material, DEFVAL(false), DEFVAL(Variant())); ClassDB::bind_method(D_METHOD("add_material", "name", "material"), &EditorNode3DGizmoPlugin::add_material); - ClassDB::bind_method(D_METHOD("get_material", "name", "gizmo"), &EditorNode3DGizmoPlugin::get_material); //, DEFVAL(Ref<EditorNode3DGizmo>())); + ClassDB::bind_method(D_METHOD("get_material", "name", "gizmo"), &EditorNode3DGizmoPlugin::get_material, DEFVAL(Ref<EditorNode3DGizmo>())); BIND_VMETHOD(MethodInfo(Variant::STRING, "get_name")); BIND_VMETHOD(MethodInfo(Variant::INT, "get_priority")); diff --git a/modules/gdnative/SCsub b/modules/gdnative/SCsub index 0e2291c1f9..bd06347afb 100644 --- a/modules/gdnative/SCsub +++ b/modules/gdnative/SCsub @@ -30,5 +30,3 @@ _, gensource = env_gdnative.CommandNoCache( env.Run(gdnative_builders.build_gdnative_api_struct, "Generating GDNative API."), ) env_gdnative.add_source_files(env.modules_sources, [gensource]) - -env.use_ptrcall = True diff --git a/modules/gdnative/config.py b/modules/gdnative/config.py index 7603e7d69d..fd860e9763 100644 --- a/modules/gdnative/config.py +++ b/modules/gdnative/config.py @@ -3,7 +3,7 @@ def can_build(env, platform): def configure(env): - env.use_ptrcall = True + pass def get_doc_classes(): diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp index 6b23ab1616..851994eff3 100644 --- a/modules/gdscript/gdscript_analyzer.cpp +++ b/modules/gdscript/gdscript_analyzer.cpp @@ -978,7 +978,7 @@ void GDScriptAnalyzer::resolve_for(GDScriptParser::ForNode *p_for) { if (!call->arguments[i]->is_constant) { all_is_constant = false; - } else { + } else if (all_is_constant) { args.write[i] = call->arguments[i]->reduced_value; } @@ -1011,11 +1011,15 @@ void GDScriptAnalyzer::resolve_for(GDScriptParser::ForNode *p_for) { } } - GDScriptParser::DataType list_type; - list_type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT; - list_type.kind = GDScriptParser::DataType::BUILTIN; - list_type.builtin_type = Variant::ARRAY; - p_for->list->set_datatype(list_type); + if (p_for->list->is_constant) { + p_for->list->set_datatype(type_from_variant(p_for->list->reduced_value, p_for->list)); + } else { + GDScriptParser::DataType list_type; + list_type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT; + list_type.kind = GDScriptParser::DataType::BUILTIN; + list_type.builtin_type = Variant::ARRAY; + p_for->list->set_datatype(list_type); + } } } } diff --git a/modules/gdscript/gdscript_byte_codegen.cpp b/modules/gdscript/gdscript_byte_codegen.cpp index 5f1c738207..a81b3298ef 100644 --- a/modules/gdscript/gdscript_byte_codegen.cpp +++ b/modules/gdscript/gdscript_byte_codegen.cpp @@ -77,11 +77,22 @@ uint32_t GDScriptByteCodeGenerator::add_or_get_name(const StringName &p_name) { uint32_t GDScriptByteCodeGenerator::add_temporary() { current_temporaries++; - return increase_stack(); + int idx = increase_stack(); +#ifdef DEBUG_ENABLED + temp_stack.push_back(idx); +#endif + return idx; } void GDScriptByteCodeGenerator::pop_temporary() { + ERR_FAIL_COND(current_temporaries == 0); current_stack_size--; +#ifdef DEBUG_ENABLED + if (temp_stack.back()->get() != current_stack_size) { + ERR_PRINT("Mismatched popping of temporary value"); + } + temp_stack.pop_back(); +#endif current_temporaries--; } @@ -111,6 +122,11 @@ void GDScriptByteCodeGenerator::write_start(GDScript *p_script, const StringName } GDScriptFunction *GDScriptByteCodeGenerator::write_end() { +#ifdef DEBUG_ENABLED + if (current_temporaries != 0) { + ERR_PRINT("Non-zero temporary variables at end of function: " + itos(current_temporaries)); + } +#endif append(GDScriptFunction::OPCODE_END, 0); if (constant_map.size()) { @@ -905,23 +921,39 @@ void GDScriptByteCodeGenerator::write_endif() { if_jmp_addrs.pop_back(); } -void GDScriptByteCodeGenerator::write_for(const Address &p_variable, const Address &p_list) { - int counter_pos = add_temporary() | (GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS); - int container_pos = add_temporary() | (GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS); +void GDScriptByteCodeGenerator::start_for(const GDScriptDataType &p_iterator_type, const GDScriptDataType &p_list_type) { + Address counter(Address::LOCAL_VARIABLE, add_local("@counter_pos", p_iterator_type), p_iterator_type); + Address container(Address::LOCAL_VARIABLE, add_local("@container_pos", p_list_type), p_list_type); - current_breaks_to_patch.push_back(List<int>()); + // Store state. + for_counter_variables.push_back(counter); + for_container_variables.push_back(container); +} + +void GDScriptByteCodeGenerator::write_for_assignment(const Address &p_variable, const Address &p_list) { + const Address &container = for_container_variables.back()->get(); // Assign container. append(GDScriptFunction::OPCODE_ASSIGN, 2); - append(container_pos); + append(container); append(p_list); + for_iterator_variables.push_back(p_variable); +} + +void GDScriptByteCodeGenerator::write_for() { + const Address &iterator = for_iterator_variables.back()->get(); + const Address &counter = for_counter_variables.back()->get(); + const Address &container = for_container_variables.back()->get(); + + current_breaks_to_patch.push_back(List<int>()); + GDScriptFunction::Opcode begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN; GDScriptFunction::Opcode iterate_opcode = GDScriptFunction::OPCODE_ITERATE; - if (p_list.type.has_type) { - if (p_list.type.kind == GDScriptDataType::BUILTIN) { - switch (p_list.type.builtin_type) { + if (container.type.has_type) { + if (container.type.kind == GDScriptDataType::BUILTIN) { + switch (container.type.builtin_type) { case Variant::INT: begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_INT; iterate_opcode = GDScriptFunction::OPCODE_ITERATE_INT; @@ -1005,9 +1037,9 @@ void GDScriptByteCodeGenerator::write_for(const Address &p_variable, const Addre // Begin loop. append(begin_opcode, 3); - append(counter_pos); - append(container_pos); - append(p_variable); + append(counter); + append(container); + append(iterator); for_jmp_addrs.push_back(opcodes.size()); append(0); // End of loop address, will be patched. append(GDScriptFunction::OPCODE_JUMP, 0); @@ -1017,9 +1049,9 @@ void GDScriptByteCodeGenerator::write_for(const Address &p_variable, const Addre int continue_addr = opcodes.size(); continue_addrs.push_back(continue_addr); append(iterate_opcode, 3); - append(counter_pos); - append(container_pos); - append(p_variable); + append(counter); + append(container); + append(iterator); for_jmp_addrs.push_back(opcodes.size()); append(0); // Jump destination, will be patched. } @@ -1042,9 +1074,10 @@ void GDScriptByteCodeGenerator::write_endfor() { } current_breaks_to_patch.pop_back(); - // Remove loop temporaries. - pop_temporary(); - pop_temporary(); + // Pop state. + for_iterator_variables.pop_back(); + for_counter_variables.pop_back(); + for_container_variables.pop_back(); } void GDScriptByteCodeGenerator::start_while_condition() { diff --git a/modules/gdscript/gdscript_byte_codegen.h b/modules/gdscript/gdscript_byte_codegen.h index a546920fb2..0173b7f820 100644 --- a/modules/gdscript/gdscript_byte_codegen.h +++ b/modules/gdscript/gdscript_byte_codegen.h @@ -43,6 +43,7 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator { Vector<int> opcodes; List<Map<StringName, int>> stack_id_stack; Map<StringName, int> stack_identifiers; + List<int> stack_identifiers_counts; Map<StringName, int> local_constants; List<GDScriptFunction::StackDebug> stack_debug; @@ -51,11 +52,16 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator { int current_stack_size = 0; int current_temporaries = 0; + int current_locals = 0; int current_line = 0; int stack_max = 0; int instr_args_max = 0; int ptrcall_max = 0; +#ifdef DEBUG_ENABLED + List<int> temp_stack; +#endif + HashMap<Variant, int, VariantHasher, VariantComparator> constant_map; Map<StringName, int> name_map; #ifdef TOOLS_ENABLED @@ -72,8 +78,12 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator { Map<Variant::ValidatedConstructor, int> constructors_map; Map<MethodBind *, int> method_bind_map; - List<int> if_jmp_addrs; // List since this can be nested. + // Lists since these can be nested. + List<int> if_jmp_addrs; List<int> for_jmp_addrs; + List<Address> for_iterator_variables; + List<Address> for_counter_variables; + List<Address> for_container_variables; List<int> while_jmp_addrs; List<int> continue_addrs; @@ -89,6 +99,7 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator { List<List<int>> match_continues_to_patch; void add_stack_identifier(const StringName &p_id, int p_stackpos) { + current_locals++; stack_identifiers[p_id] = p_stackpos; if (debug_stack) { block_identifiers[p_id] = p_stackpos; @@ -102,17 +113,26 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator { } void push_stack_identifiers() { + stack_identifiers_counts.push_back(current_locals); stack_id_stack.push_back(stack_identifiers); if (debug_stack) { - block_identifier_stack.push_back(block_identifiers); + Map<StringName, int> block_ids(block_identifiers); + block_identifier_stack.push_back(block_ids); block_identifiers.clear(); } } void pop_stack_identifiers() { + current_locals = stack_identifiers_counts.back()->get(); + stack_identifiers_counts.pop_back(); stack_identifiers = stack_id_stack.back()->get(); - current_stack_size = stack_identifiers.size() + current_temporaries; stack_id_stack.pop_back(); +#ifdef DEBUG_ENABLED + if (current_temporaries != 0) { + ERR_PRINT("Leaving block with non-zero temporary variables: " + itos(current_temporaries)); + } +#endif + current_stack_size = current_locals; if (debug_stack) { for (Map<StringName, int>::Element *E = block_identifiers.front(); E; E = E->next()) { @@ -397,7 +417,9 @@ public: virtual void write_if(const Address &p_condition) override; virtual void write_else() override; virtual void write_endif() override; - virtual void write_for(const Address &p_variable, const Address &p_list) override; + virtual void start_for(const GDScriptDataType &p_iterator_type, const GDScriptDataType &p_list_type) override; + virtual void write_for_assignment(const Address &p_variable, const Address &p_list) override; + virtual void write_for() override; virtual void write_endfor() override; virtual void start_while_condition() override; virtual void write_while(const Address &p_condition) override; diff --git a/modules/gdscript/gdscript_codegen.h b/modules/gdscript/gdscript_codegen.h index 2616a34719..decab3df0b 100644 --- a/modules/gdscript/gdscript_codegen.h +++ b/modules/gdscript/gdscript_codegen.h @@ -139,7 +139,9 @@ public: // virtual void write_elseif(const Address &p_condition) = 0; This kind of makes things more difficult for no real benefit. virtual void write_else() = 0; virtual void write_endif() = 0; - virtual void write_for(const Address &p_variable, const Address &p_list) = 0; + virtual void start_for(const GDScriptDataType &p_iterator_type, const GDScriptDataType &p_list_type) = 0; + virtual void write_for_assignment(const Address &p_variable, const Address &p_list) = 0; + virtual void write_for() = 0; virtual void write_endfor() = 0; virtual void start_while_condition() = 0; // Used to allow a jump to the expression evaluation. virtual void write_while(const Address &p_condition) = 0; diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp index 69fe6d27cc..3d327cebeb 100644 --- a/modules/gdscript/gdscript_compiler.cpp +++ b/modules/gdscript/gdscript_compiler.cpp @@ -437,7 +437,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code gen->pop_temporary(); } - return source; + return result; } break; case GDScriptParser::Node::CALL: { const GDScriptParser::CallNode *call = static_cast<const GDScriptParser::CallNode *>(p_expression); @@ -1474,13 +1474,27 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui codegen.start_block(); // Evaluate the match expression. + GDScriptCodeGenerator::Address value_local = codegen.add_local("@match_value", _gdtype_from_datatype(match->test->get_datatype())); GDScriptCodeGenerator::Address value = _parse_expression(codegen, error, match->test); if (error) { return error; } + // Assign to local. + // TODO: This can be improved by passing the target to parse_expression(). + gen->write_assign(value_local, value); + + if (value.mode == GDScriptCodeGenerator::Address::TEMPORARY) { + codegen.generator->pop_temporary(); + } + // Then, let's save the type of the value in the stack too, so we can reuse for later comparisons. - GDScriptCodeGenerator::Address type = codegen.add_temporary(); + GDScriptDataType typeof_type; + typeof_type.has_type = true; + typeof_type.kind = GDScriptDataType::BUILTIN; + typeof_type.builtin_type = Variant::INT; + GDScriptCodeGenerator::Address type = codegen.add_local("@match_type", typeof_type); + Vector<GDScriptCodeGenerator::Address> typeof_args; typeof_args.push_back(value); gen->write_call_builtin(type, GDScriptFunctions::TYPE_OF, typeof_args); @@ -1534,12 +1548,6 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui gen->write_endif(); } - gen->pop_temporary(); - - if (value.mode == GDScriptCodeGenerator::Address::TEMPORARY) { - codegen.generator->pop_temporary(); - } - gen->end_match(); } break; case GDScriptParser::Node::IF: { @@ -1577,12 +1585,20 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui codegen.start_block(); GDScriptCodeGenerator::Address iterator = codegen.add_local(for_n->variable->name, _gdtype_from_datatype(for_n->variable->get_datatype())); + gen->start_for(iterator.type, _gdtype_from_datatype(for_n->list->get_datatype())); + GDScriptCodeGenerator::Address list = _parse_expression(codegen, error, for_n->list); if (error) { return error; } - gen->write_for(iterator, list); + gen->write_for_assignment(iterator, list); + + if (list.mode == GDScriptCodeGenerator::Address::TEMPORARY) { + codegen.generator->pop_temporary(); + } + + gen->write_for(); error = _parse_block(codegen, for_n->loop); if (error) { @@ -1591,10 +1607,6 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui gen->write_endfor(); - if (list.mode == GDScriptCodeGenerator::Address::TEMPORARY) { - codegen.generator->pop_temporary(); - } - codegen.end_block(); } break; case GDScriptParser::Node::WHILE: { diff --git a/modules/gdscript/gdscript_disassembler.cpp b/modules/gdscript/gdscript_disassembler.cpp index c918251772..92a44c57f8 100644 --- a/modules/gdscript/gdscript_disassembler.cpp +++ b/modules/gdscript/gdscript_disassembler.cpp @@ -360,15 +360,12 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const { incr += 4; } break; case OPCODE_CAST_TO_NATIVE: { - Variant class_name = _constants_ptr[_code_ptr[ip + 1]]; - GDScriptNativeClass *nc = Object::cast_to<GDScriptNativeClass>(class_name.operator Object *()); - text += "cast native "; text += DADDR(2); text += " = "; text += DADDR(1); text += " as "; - text += nc->get_name(); + text += DADDR(3); incr += 4; } break; diff --git a/modules/mono/config.py b/modules/mono/config.py index d060ae9b28..c4a6b408e6 100644 --- a/modules/mono/config.py +++ b/modules/mono/config.py @@ -11,7 +11,6 @@ def configure(env): if platform not in supported_platforms: raise RuntimeError("This module does not currently support building for this platform") - env.use_ptrcall = True env.add_module_version_string("mono") from SCons.Script import BoolVariable, PathVariable, Variables, Help diff --git a/platform/linuxbsd/detect.py b/platform/linuxbsd/detect.py index a1bc5867c5..a8bc3a09f6 100644 --- a/platform/linuxbsd/detect.py +++ b/platform/linuxbsd/detect.py @@ -129,7 +129,6 @@ def configure(env): if "clang++" not in os.path.basename(env["CXX"]): env["CC"] = "clang" env["CXX"] = "clang++" - env.Append(CPPDEFINES=["TYPED_METHOD_BIND"]) env.extra_suffix = ".llvm" + env.extra_suffix if env["use_lld"]: diff --git a/platform/linuxbsd/display_server_x11.cpp b/platform/linuxbsd/display_server_x11.cpp index 5fa737af8e..74c69c0823 100644 --- a/platform/linuxbsd/display_server_x11.cpp +++ b/platform/linuxbsd/display_server_x11.cpp @@ -552,6 +552,60 @@ String DisplayServerX11::clipboard_get() const { return ret; } +Bool DisplayServerX11::_predicate_clipboard_save_targets(Display *display, XEvent *event, XPointer arg) { + if (event->xany.window == *(Window *)arg) { + return (event->type == SelectionRequest) || + (event->type == SelectionNotify); + } else { + return False; + } +} + +void DisplayServerX11::_clipboard_transfer_ownership(Atom p_source, Window x11_window) const { + _THREAD_SAFE_METHOD_ + + Window selection_owner = XGetSelectionOwner(x11_display, p_source); + + if (selection_owner != x11_window) { + return; + } + + // Block events polling while processing selection events. + MutexLock mutex_lock(events_mutex); + + Atom clipboard_manager = XInternAtom(x11_display, "CLIPBOARD_MANAGER", False); + Atom save_targets = XInternAtom(x11_display, "SAVE_TARGETS", False); + XConvertSelection(x11_display, clipboard_manager, save_targets, None, + x11_window, CurrentTime); + + // Process events from the queue. + while (true) { + if (!_wait_for_events()) { + // Error or timeout, abort. + break; + } + + // Non-blocking wait for next event and remove it from the queue. + XEvent ev; + while (XCheckIfEvent(x11_display, &ev, _predicate_clipboard_save_targets, (XPointer)&x11_window)) { + switch (ev.type) { + case SelectionRequest: + _handle_selection_request_event(&(ev.xselectionrequest)); + break; + + case SelectionNotify: { + if (ev.xselection.target == save_targets) { + // Once SelectionNotify is received, we're done whether it succeeded or not. + return; + } + + break; + } + } + } + } +} + int DisplayServerX11::get_screen_count() const { _THREAD_SAFE_METHOD_ @@ -2291,53 +2345,105 @@ void DisplayServerX11::_handle_key_event(WindowID p_window, XKeyEvent *p_event, Input::get_singleton()->accumulate_input_event(k); } -void DisplayServerX11::_handle_selection_request_event(XSelectionRequestEvent *p_event) { - XEvent respond; - if (p_event->target == XInternAtom(x11_display, "UTF8_STRING", 0) || - p_event->target == XInternAtom(x11_display, "COMPOUND_TEXT", 0) || - p_event->target == XInternAtom(x11_display, "TEXT", 0) || - p_event->target == XA_STRING || - p_event->target == XInternAtom(x11_display, "text/plain;charset=utf-8", 0) || - p_event->target == XInternAtom(x11_display, "text/plain", 0)) { - // Directly using internal clipboard because we know our window - // is the owner during a selection request. - CharString clip = internal_clipboard.utf8(); - XChangeProperty(x11_display, - p_event->requestor, - p_event->property, - p_event->target, - 8, - PropModeReplace, - (unsigned char *)clip.get_data(), - clip.length()); - respond.xselection.property = p_event->property; - } else if (p_event->target == XInternAtom(x11_display, "TARGETS", 0)) { - Atom data[7]; +Atom DisplayServerX11::_process_selection_request_target(Atom p_target, Window p_requestor, Atom p_property) const { + if (p_target == XInternAtom(x11_display, "TARGETS", 0)) { + // Request to list all supported targets. + Atom data[9]; data[0] = XInternAtom(x11_display, "TARGETS", 0); - data[1] = XInternAtom(x11_display, "UTF8_STRING", 0); - data[2] = XInternAtom(x11_display, "COMPOUND_TEXT", 0); - data[3] = XInternAtom(x11_display, "TEXT", 0); - data[4] = XA_STRING; - data[5] = XInternAtom(x11_display, "text/plain;charset=utf-8", 0); - data[6] = XInternAtom(x11_display, "text/plain", 0); + data[1] = XInternAtom(x11_display, "SAVE_TARGETS", 0); + data[2] = XInternAtom(x11_display, "MULTIPLE", 0); + data[3] = XInternAtom(x11_display, "UTF8_STRING", 0); + data[4] = XInternAtom(x11_display, "COMPOUND_TEXT", 0); + data[5] = XInternAtom(x11_display, "TEXT", 0); + data[6] = XA_STRING; + data[7] = XInternAtom(x11_display, "text/plain;charset=utf-8", 0); + data[8] = XInternAtom(x11_display, "text/plain", 0); XChangeProperty(x11_display, - p_event->requestor, - p_event->property, + p_requestor, + p_property, XA_ATOM, 32, PropModeReplace, (unsigned char *)&data, sizeof(data) / sizeof(data[0])); - respond.xselection.property = p_event->property; - + return p_property; + } else if (p_target == XInternAtom(x11_display, "SAVE_TARGETS", 0)) { + // Request to check if SAVE_TARGETS is supported, nothing special to do. + XChangeProperty(x11_display, + p_requestor, + p_property, + XInternAtom(x11_display, "NULL", False), + 32, + PropModeReplace, + nullptr, + 0); + return p_property; + } else if (p_target == XInternAtom(x11_display, "UTF8_STRING", 0) || + p_target == XInternAtom(x11_display, "COMPOUND_TEXT", 0) || + p_target == XInternAtom(x11_display, "TEXT", 0) || + p_target == XA_STRING || + p_target == XInternAtom(x11_display, "text/plain;charset=utf-8", 0) || + p_target == XInternAtom(x11_display, "text/plain", 0)) { + // Directly using internal clipboard because we know our window + // is the owner during a selection request. + CharString clip = internal_clipboard.utf8(); + XChangeProperty(x11_display, + p_requestor, + p_property, + p_target, + 8, + PropModeReplace, + (unsigned char *)clip.get_data(), + clip.length()); + return p_property; } else { - char *targetname = XGetAtomName(x11_display, p_event->target); - printf("No Target '%s'\n", targetname); - if (targetname) { - XFree(targetname); + char *target_name = XGetAtomName(x11_display, p_target); + printf("Target '%s' not supported.\n", target_name); + if (target_name) { + XFree(target_name); } + return None; + } +} + +void DisplayServerX11::_handle_selection_request_event(XSelectionRequestEvent *p_event) const { + XEvent respond; + if (p_event->target == XInternAtom(x11_display, "MULTIPLE", 0)) { + // Request for multiple target conversions at once. + Atom atom_pair = XInternAtom(x11_display, "ATOM_PAIR", False); respond.xselection.property = None; + + Atom type; + int format; + unsigned long len; + unsigned long remaining; + unsigned char *data = nullptr; + if (XGetWindowProperty(x11_display, p_event->requestor, p_event->property, 0, LONG_MAX, False, atom_pair, &type, &format, &len, &remaining, &data) == Success) { + if ((len >= 2) && data) { + Atom *targets = (Atom *)data; + for (uint64_t i = 0; i < len; i += 2) { + Atom target = targets[i]; + Atom &property = targets[i + 1]; + property = _process_selection_request_target(target, p_event->requestor, property); + } + + XChangeProperty(x11_display, + p_event->requestor, + p_event->property, + atom_pair, + 32, + PropModeReplace, + (unsigned char *)targets, + len); + + respond.xselection.property = p_event->property; + } + XFree(data); + } + } else { + // Request for target conversion. + respond.xselection.property = _process_selection_request_target(p_event->target, p_event->requestor, p_event->property); } respond.xselection.type = SelectionNotify; @@ -2473,32 +2579,43 @@ Bool DisplayServerX11::_predicate_all_events(Display *display, XEvent *event, XP return True; } -void DisplayServerX11::_poll_events() { +bool DisplayServerX11::_wait_for_events() const { int x11_fd = ConnectionNumber(x11_display); fd_set in_fds; - while (!events_thread_done) { - XFlush(x11_display); + XFlush(x11_display); + + FD_ZERO(&in_fds); + FD_SET(x11_fd, &in_fds); - FD_ZERO(&in_fds); - FD_SET(x11_fd, &in_fds); + struct timeval tv; + tv.tv_usec = 0; + tv.tv_sec = 1; - struct timeval tv; - tv.tv_usec = 0; - tv.tv_sec = 1; + // Wait for next event or timeout. + int num_ready_fds = select(x11_fd + 1, &in_fds, NULL, NULL, &tv); - // Wait for next event or timeout. - int num_ready_fds = select(x11_fd + 1, &in_fds, NULL, NULL, &tv); + if (num_ready_fds > 0) { + // Event received. + return true; + } else { + // Error or timeout. if (num_ready_fds < 0) { - ERR_PRINT("_poll_events: select error: " + itos(errno)); + ERR_PRINT("_wait_for_events: select error: " + itos(errno)); } + return false; + } +} + +void DisplayServerX11::_poll_events() { + while (!events_thread_done) { + _wait_for_events(); // Process events from the queue. { MutexLock mutex_lock(events_mutex); - // Non-blocking wait for next event - // and remove it from the queue. + // Non-blocking wait for next event and remove it from the queue. XEvent ev; while (XCheckIfEvent(x11_display, &ev, _predicate_all_events, nullptr)) { // Check if the input manager wants to process the event. @@ -4068,6 +4185,11 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode } DisplayServerX11::~DisplayServerX11() { + // Send owned clipboard data to clipboard manager before exit. + Window x11_main_window = windows[MAIN_WINDOW_ID].x11_window; + _clipboard_transfer_ownership(XA_PRIMARY, x11_main_window); + _clipboard_transfer_ownership(XInternAtom(x11_display, "CLIPBOARD", 0), x11_main_window); + events_thread_done = true; Thread::wait_to_finish(events_thread); memdelete(events_thread); diff --git a/platform/linuxbsd/display_server_x11.h b/platform/linuxbsd/display_server_x11.h index 9ff28b9ed2..682f1c8ef3 100644 --- a/platform/linuxbsd/display_server_x11.h +++ b/platform/linuxbsd/display_server_x11.h @@ -204,10 +204,13 @@ class DisplayServerX11 : public DisplayServer { Point2i center; void _handle_key_event(WindowID p_window, XKeyEvent *p_event, LocalVector<XEvent> &p_events, uint32_t &p_event_index, bool p_echo = false); - void _handle_selection_request_event(XSelectionRequestEvent *p_event); + + Atom _process_selection_request_target(Atom p_target, Window p_requestor, Atom p_property) const; + void _handle_selection_request_event(XSelectionRequestEvent *p_event) const; String _clipboard_get_impl(Atom p_source, Window x11_window, Atom target) const; String _clipboard_get(Atom p_source, Window x11_window) const; + void _clipboard_transfer_ownership(Atom p_source, Window x11_window) const; //bool minimized; //bool window_has_focus; @@ -262,10 +265,12 @@ class DisplayServerX11 : public DisplayServer { bool events_thread_done = false; LocalVector<XEvent> polled_events; static void _poll_events_thread(void *ud); + bool _wait_for_events() const; void _poll_events(); static Bool _predicate_all_events(Display *display, XEvent *event, XPointer arg); static Bool _predicate_clipboard_selection(Display *display, XEvent *event, XPointer arg); + static Bool _predicate_clipboard_save_targets(Display *display, XEvent *event, XPointer arg); protected: void _window_changed(XEvent *event); diff --git a/platform/server/detect.py b/platform/server/detect.py index a3f60b0710..d9ac357679 100644 --- a/platform/server/detect.py +++ b/platform/server/detect.py @@ -94,7 +94,6 @@ def configure(env): if "clang++" not in os.path.basename(env["CXX"]): env["CC"] = "clang" env["CXX"] = "clang++" - env.Append(CPPDEFINES=["TYPED_METHOD_BIND"]) env.extra_suffix = ".llvm" + env.extra_suffix if env["use_coverage"]: diff --git a/scene/gui/control.h b/scene/gui/control.h index 85b3227884..e4fe0bb25d 100644 --- a/scene/gui/control.h +++ b/scene/gui/control.h @@ -157,8 +157,6 @@ private: Vector2 scale; Vector2 pivot_offset; - bool pending_resize; - int h_size_flags; int v_size_flags; float expand; diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp index f4e31c45d2..8aad5f262d 100644 --- a/scene/gui/scroll_container.cpp +++ b/scene/gui/scroll_container.cpp @@ -414,12 +414,12 @@ void ScrollContainer::update_scrollbars() { bool hide_scroll_v = !scroll_v || min.height <= size.height; bool hide_scroll_h = !scroll_h || min.width <= size.width; + v_scroll->set_max(min.height); if (hide_scroll_v) { v_scroll->hide(); scroll.y = 0; } else { v_scroll->show(); - v_scroll->set_max(min.height); if (hide_scroll_h) { v_scroll->set_page(size.height); } else { @@ -429,12 +429,12 @@ void ScrollContainer::update_scrollbars() { scroll.y = v_scroll->get_value(); } + h_scroll->set_max(min.width); if (hide_scroll_h) { h_scroll->hide(); scroll.x = 0; } else { h_scroll->show(); - h_scroll->set_max(min.width); if (hide_scroll_v) { h_scroll->set_page(size.width); } else { |