Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[4.3] Cherry-picks for the 4.3 (4.3.1) branch - 1st core bugs batch #931

Merged
merged 26 commits into from
Jan 18, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
4af5797
Fix displaying of embedded `Window`
Sauermann Aug 1, 2023
dc73355
Parse fragment from URL
timothyqiu May 22, 2024
b956d97
Remove unused `initialize_ref`
rune-scape Jul 3, 2024
b753704
Refactor ref-counting code and fix ref counted releasing before aquiring
rune-scape Jun 18, 2024
2ca3e06
Add missing CallableCustomMethodPointer for const methods
rune-scape Jul 28, 2024
4165c30
Fix pink GradientTexture2D
matheusmdx Jul 25, 2024
3c84894
Assign return value on Variant operator failure
aaronp64 Aug 5, 2024
a89ae6b
WorkerThreadPool: Enhance lifetime for more flexibility
RandomShaper Sep 10, 2024
96ac04c
Make languages' thread enter/exit more resilient
RandomShaper Sep 10, 2024
b3d874c
Revert "WorkerThreadPool: Enhance lifetime for more flexibility"
RandomShaper Sep 13, 2024
7a49630
WorkerThreadPool: Improve logic
RandomShaper Sep 16, 2024
053bd3d
WorkerThreadPool: Refactor running and exit-requested as runlevels
RandomShaper Sep 13, 2024
33820ea
WorkerThreadPool: Add safety point between languages finished and poo…
RandomShaper Sep 16, 2024
ffa2691
Avoid duplicating signals from scene instances into packed scenes
cixil Sep 21, 2024
bbe2ec5
Revert "Avoid duplicating signals from scene instances into packed sc…
akien-mga Dec 10, 2024
2acdc35
Make internal unique scene resource ID deterministic
reduz Sep 23, 2024
ae159c6
Fix `atr_n()` behavior when auto translation is disabled
timothyqiu Sep 29, 2024
4b29b2e
Allow use RID with `in` operator for Arrays and Dictionaries
dustdfg Oct 20, 2024
85ad622
Fixed occlusion culling for double builds by enforcing float conversi…
Rudolph-B Nov 2, 2024
dca6227
Fix a few more super calls in `get_configuration_warnings` methods
AThousandShips Nov 8, 2024
434c9b9
Force `get_thread_count()` to `1` if single threaded
adamscott Nov 19, 2024
e949fb7
ResourceLoader: Report appropriate error code when no suitable loader…
RandomShaper Nov 21, 2024
5293087
Make loading translations from threads safe
RandomShaper Nov 22, 2024
31b13f3
Fix error when use relative #include in .gdshader / .gdshaderinc file
jsjtxietian Aug 6, 2024
736126b
Fix handling of leading `..` in simplify_path
demolke Dec 5, 2024
2f0f68c
[Web] Fix `DirAccess::unlink()` not updating the IDBFS
adamscott Dec 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 22 additions & 11 deletions core/io/resource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,31 +100,42 @@ void Resource::set_path_cache(const String &p_path) {
path_cache = p_path;
}

static thread_local RandomPCG unique_id_gen(0, RandomPCG::DEFAULT_INC);

void Resource::seed_scene_unique_id(uint32_t p_seed) {
unique_id_gen.seed(p_seed);
}

String Resource::generate_scene_unique_id() {
// Generate a unique enough hash, but still user-readable.
// If it's not unique it does not matter because the saver will try again.
OS::DateTime dt = OS::get_singleton()->get_datetime();
uint32_t hash = hash_murmur3_one_32(OS::get_singleton()->get_ticks_usec());
hash = hash_murmur3_one_32(dt.year, hash);
hash = hash_murmur3_one_32(dt.month, hash);
hash = hash_murmur3_one_32(dt.day, hash);
hash = hash_murmur3_one_32(dt.hour, hash);
hash = hash_murmur3_one_32(dt.minute, hash);
hash = hash_murmur3_one_32(dt.second, hash);
hash = hash_murmur3_one_32(Math::rand(), hash);
if (unique_id_gen.get_seed() == 0) {
OS::DateTime dt = OS::get_singleton()->get_datetime();
uint32_t hash = hash_murmur3_one_32(OS::get_singleton()->get_ticks_usec());
hash = hash_murmur3_one_32(dt.year, hash);
hash = hash_murmur3_one_32(dt.month, hash);
hash = hash_murmur3_one_32(dt.day, hash);
hash = hash_murmur3_one_32(dt.hour, hash);
hash = hash_murmur3_one_32(dt.minute, hash);
hash = hash_murmur3_one_32(dt.second, hash);
hash = hash_murmur3_one_32(Math::rand(), hash);
unique_id_gen.seed(hash);
}

uint32_t random_num = unique_id_gen.rand();

static constexpr uint32_t characters = 5;
static constexpr uint32_t char_count = ('z' - 'a');
static constexpr uint32_t base = char_count + ('9' - '0');
String id;
for (uint32_t i = 0; i < characters; i++) {
uint32_t c = hash % base;
uint32_t c = random_num % base;
if (c < char_count) {
id += String::chr('a' + c);
} else {
id += String::chr('0' + (c - char_count));
}
hash /= base;
random_num /= base;
}

return id;
Expand Down
1 change: 1 addition & 0 deletions core/io/resource.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ class Resource : public RefCounted {
virtual void set_path_cache(const String &p_path); // Set raw path without involving resource cache.
_FORCE_INLINE_ bool is_built_in() const { return path_cache.is_empty() || path_cache.contains("::") || path_cache.begins_with("local://"); }

static void seed_scene_unique_id(uint32_t p_seed);
static String generate_scene_unique_id();
void set_scene_unique_id(const String &p_id);
String get_scene_unique_id() const;
Expand Down
2 changes: 2 additions & 0 deletions core/io/resource_format_binary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2121,6 +2121,8 @@ static String _resource_get_class(Ref<Resource> p_resource) {
}

Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags) {
Resource::seed_scene_unique_id(p_path.hash());

Error err;
Ref<FileAccess> f;
if (p_flags & ResourceSaver::FLAG_COMPRESS) {
Expand Down
22 changes: 21 additions & 1 deletion core/io/resource_loader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -307,14 +307,34 @@ Ref<Resource> ResourceLoader::_load(const String &p_path, const String &p_origin
return res;
}

#ifdef TOOLS_ENABLED
if (Engine::get_singleton()->is_editor_hint()) {
if (ResourceFormatImporter::get_singleton()->get_importer_by_extension(p_path.get_extension()).is_valid()) {
// The format is known to the editor, but the file hasn't been imported
// (otherwise, ResourceFormatImporter would have been found as a suitable loader).
found = true;
if (r_error) {
*r_error = ERR_FILE_NOT_FOUND;
}
}
}
#endif
ERR_FAIL_COND_V_MSG(found, Ref<Resource>(),
vformat("Failed loading resource: %s. Make sure resources have been imported by opening the project in the editor at least once.", p_path));

#ifdef TOOLS_ENABLED
Ref<FileAccess> file_check = FileAccess::create(FileAccess::ACCESS_RESOURCES);
ERR_FAIL_COND_V_MSG(!file_check->file_exists(p_path), Ref<Resource>(), vformat("Resource file not found: %s (expected type: %s)", p_path, p_type_hint));
if (!file_check->file_exists(p_path)) {
if (r_error) {
*r_error = ERR_FILE_NOT_FOUND;
}
ERR_FAIL_V_MSG(Ref<Resource>(), vformat("Resource file not found: %s (expected type: %s)", p_path, p_type_hint));
}
#endif

if (r_error) {
*r_error = ERR_FILE_UNRECOGNIZED;
}
ERR_FAIL_V_MSG(Ref<Resource>(), vformat("No loader found for resource: %s (expected type: %s)", p_path, p_type_hint));
}

Expand Down
137 changes: 48 additions & 89 deletions core/object/callable_method_pointer.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
#include "core/variant/binder_common.h"
#include "core/variant/callable.h"

#include <type_traits>

class CallableCustomMethodPointerBase : public CallableCustom {
uint32_t *comp_ptr = nullptr;
uint32_t comp_size;
Expand Down Expand Up @@ -79,12 +81,13 @@ class CallableCustomMethodPointerBase : public CallableCustom {
virtual uint32_t hash() const;
};

template <typename T, typename... P>
template <typename T, typename R, typename... P>
class CallableCustomMethodPointer : public CallableCustomMethodPointerBase {
struct Data {
T *instance;
uint64_t object_id;
void (T::*method)(P...);
R(T::*method)
(P...);
} data;

public:
Expand All @@ -102,10 +105,14 @@ class CallableCustomMethodPointer : public CallableCustomMethodPointerBase {

virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const {
ERR_FAIL_NULL_MSG(ObjectDB::get_instance(ObjectID(data.object_id)), "Invalid Object id '" + uitos(data.object_id) + "', can't call method.");
call_with_variant_args(data.instance, data.method, p_arguments, p_argcount, r_call_error);
if constexpr (std::is_same<R, void>::value) {
call_with_variant_args(data.instance, data.method, p_arguments, p_argcount, r_call_error);
} else {
call_with_variant_args_ret(data.instance, data.method, p_arguments, p_argcount, r_return_value, r_call_error);
}
}

CallableCustomMethodPointer(T *p_instance, void (T::*p_method)(P...)) {
CallableCustomMethodPointer(T *p_instance, R (T::*p_method)(P...)) {
memset(&data, 0, sizeof(Data)); // Clear beforehand, may have padding bytes.
data.instance = p_instance;
data.object_id = p_instance->get_instance_id();
Expand All @@ -120,70 +127,32 @@ Callable create_custom_callable_function_pointer(T *p_instance,
const char *p_func_text,
#endif
void (T::*p_method)(P...)) {
typedef CallableCustomMethodPointer<T, P...> CCMP; // Messes with memnew otherwise.
typedef CallableCustomMethodPointer<T, void, P...> CCMP; // Messes with memnew otherwise.
CCMP *ccmp = memnew(CCMP(p_instance, p_method));
#ifdef DEBUG_METHODS_ENABLED
ccmp->set_text(p_func_text + 1); // Try to get rid of the ampersand.
#endif
return Callable(ccmp);
}

// VERSION WITH RETURN

template <typename T, typename R, typename... P>
class CallableCustomMethodPointerRet : public CallableCustomMethodPointerBase {
struct Data {
T *instance;
uint64_t object_id;
R(T::*method)
(P...);
} data;

public:
virtual ObjectID get_object() const {
if (ObjectDB::get_instance(ObjectID(data.object_id)) == nullptr) {
return ObjectID();
}
return data.instance->get_instance_id();
}

virtual int get_argument_count(bool &r_is_valid) const {
r_is_valid = true;
return sizeof...(P);
}

virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const {
ERR_FAIL_NULL_MSG(ObjectDB::get_instance(ObjectID(data.object_id)), "Invalid Object id '" + uitos(data.object_id) + "', can't call method.");
call_with_variant_args_ret(data.instance, data.method, p_arguments, p_argcount, r_return_value, r_call_error);
}

CallableCustomMethodPointerRet(T *p_instance, R (T::*p_method)(P...)) {
memset(&data, 0, sizeof(Data)); // Clear beforehand, may have padding bytes.
data.instance = p_instance;
data.object_id = p_instance->get_instance_id();
data.method = p_method;
_setup((uint32_t *)&data, sizeof(Data));
}
};

template <typename T, typename R, typename... P>
Callable create_custom_callable_function_pointer(T *p_instance,
#ifdef DEBUG_METHODS_ENABLED
const char *p_func_text,
#endif
R (T::*p_method)(P...)) {
typedef CallableCustomMethodPointerRet<T, R, P...> CCMP; // Messes with memnew otherwise.
typedef CallableCustomMethodPointer<T, R, P...> CCMP; // Messes with memnew otherwise.
CCMP *ccmp = memnew(CCMP(p_instance, p_method));
#ifdef DEBUG_METHODS_ENABLED
ccmp->set_text(p_func_text + 1); // Try to get rid of the ampersand.
#endif
return Callable(ccmp);
}

// CONST VERSION WITH RETURN
// CONST VERSION

template <typename T, typename R, typename... P>
class CallableCustomMethodPointerRetC : public CallableCustomMethodPointerBase {
class CallableCustomMethodPointerC : public CallableCustomMethodPointerBase {
struct Data {
T *instance;
uint64_t object_id;
Expand All @@ -206,10 +175,14 @@ class CallableCustomMethodPointerRetC : public CallableCustomMethodPointerBase {

virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override {
ERR_FAIL_NULL_MSG(ObjectDB::get_instance(ObjectID(data.object_id)), "Invalid Object id '" + uitos(data.object_id) + "', can't call method.");
call_with_variant_args_retc(data.instance, data.method, p_arguments, p_argcount, r_return_value, r_call_error);
if constexpr (std::is_same<R, void>::value) {
call_with_variant_argsc(data.instance, data.method, p_arguments, p_argcount, r_call_error);
} else {
call_with_variant_args_retc(data.instance, data.method, p_arguments, p_argcount, r_return_value, r_call_error);
}
}

CallableCustomMethodPointerRetC(T *p_instance, R (T::*p_method)(P...) const) {
CallableCustomMethodPointerC(T *p_instance, R (T::*p_method)(P...) const) {
memset(&data, 0, sizeof(Data)); // Clear beforehand, may have padding bytes.
data.instance = p_instance;
data.object_id = p_instance->get_instance_id();
Expand All @@ -218,13 +191,27 @@ class CallableCustomMethodPointerRetC : public CallableCustomMethodPointerBase {
}
};

template <typename T, typename... P>
Callable create_custom_callable_function_pointer(T *p_instance,
#ifdef DEBUG_METHODS_ENABLED
const char *p_func_text,
#endif
void (T::*p_method)(P...) const) {
typedef CallableCustomMethodPointerC<T, void, P...> CCMP; // Messes with memnew otherwise.
CCMP *ccmp = memnew(CCMP(p_instance, p_method));
#ifdef DEBUG_METHODS_ENABLED
ccmp->set_text(p_func_text + 1); // Try to get rid of the ampersand.
#endif
return Callable(ccmp);
}

template <typename T, typename R, typename... P>
Callable create_custom_callable_function_pointer(T *p_instance,
#ifdef DEBUG_METHODS_ENABLED
const char *p_func_text,
#endif
R (T::*p_method)(P...) const) {
typedef CallableCustomMethodPointerRetC<T, R, P...> CCMP; // Messes with memnew otherwise.
typedef CallableCustomMethodPointerC<T, R, P...> CCMP; // Messes with memnew otherwise.
CCMP *ccmp = memnew(CCMP(p_instance, p_method));
#ifdef DEBUG_METHODS_ENABLED
ccmp->set_text(p_func_text + 1); // Try to get rid of the ampersand.
Expand All @@ -240,10 +227,11 @@ Callable create_custom_callable_function_pointer(T *p_instance,

// STATIC VERSIONS

template <typename... P>
template <typename R, typename... P>
class CallableCustomStaticMethodPointer : public CallableCustomMethodPointerBase {
struct Data {
void (*method)(P...);
R(*method)
(P...);
} data;

public:
Expand All @@ -261,70 +249,41 @@ class CallableCustomStaticMethodPointer : public CallableCustomMethodPointerBase
}

virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override {
call_with_variant_args_static_ret(data.method, p_arguments, p_argcount, r_return_value, r_call_error);
r_return_value = Variant();
if constexpr (std::is_same<R, void>::value) {
call_with_variant_args_static(data.method, p_arguments, p_argcount, r_call_error);
} else {
call_with_variant_args_static_ret(data.method, p_arguments, p_argcount, r_return_value, r_call_error);
}
}

CallableCustomStaticMethodPointer(void (*p_method)(P...)) {
CallableCustomStaticMethodPointer(R (*p_method)(P...)) {
memset(&data, 0, sizeof(Data)); // Clear beforehand, may have padding bytes.
data.method = p_method;
_setup((uint32_t *)&data, sizeof(Data));
}
};

template <typename T, typename... P>
template <typename... P>
Callable create_custom_callable_static_function_pointer(
#ifdef DEBUG_METHODS_ENABLED
const char *p_func_text,
#endif
void (*p_method)(P...)) {
typedef CallableCustomStaticMethodPointer<P...> CCMP; // Messes with memnew otherwise.
typedef CallableCustomStaticMethodPointer<void, P...> CCMP; // Messes with memnew otherwise.
CCMP *ccmp = memnew(CCMP(p_method));
#ifdef DEBUG_METHODS_ENABLED
ccmp->set_text(p_func_text + 1); // Try to get rid of the ampersand.
#endif
return Callable(ccmp);
}

template <typename R, typename... P>
class CallableCustomStaticMethodPointerRet : public CallableCustomMethodPointerBase {
struct Data {
R(*method)
(P...);
} data;

public:
virtual bool is_valid() const override {
return true;
}

virtual ObjectID get_object() const override {
return ObjectID();
}

virtual int get_argument_count(bool &r_is_valid) const override {
r_is_valid = true;
return sizeof...(P);
}

virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override {
call_with_variant_args_static_ret(data.method, p_arguments, p_argcount, r_return_value, r_call_error);
}

CallableCustomStaticMethodPointerRet(R (*p_method)(P...)) {
memset(&data, 0, sizeof(Data)); // Clear beforehand, may have padding bytes.
data.method = p_method;
_setup((uint32_t *)&data, sizeof(Data));
}
};

template <typename R, typename... P>
Callable create_custom_callable_static_function_pointer(
#ifdef DEBUG_METHODS_ENABLED
const char *p_func_text,
#endif
R (*p_method)(P...)) {
typedef CallableCustomStaticMethodPointerRet<R, P...> CCMP; // Messes with memnew otherwise.
typedef CallableCustomStaticMethodPointer<R, P...> CCMP; // Messes with memnew otherwise.
CCMP *ccmp = memnew(CCMP(p_method));
#ifdef DEBUG_METHODS_ENABLED
ccmp->set_text(p_func_text + 1); // Try to get rid of the ampersand.
Expand Down
Loading
Loading