Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
e540c59
Add missing `cstdlib` include for `EXIT_SUCCESS` and `free`
Fahien Dec 16, 2025
4a6869c
[CI] Remove cache clean action
AThousandShips Nov 18, 2025
716f630
Configure SDL assuming we, in fact, have a libc.
zeux Sep 2, 2025
deeaadb
libpng: Update to 1.6.51
Chubercik Jun 30, 2025
4ae07db
libpng: Update to 1.6.53
akien-mga Dec 12, 2025
c961e66
mbedTLS: Update to version 3.6.5
akien-mga Oct 20, 2025
b65c5d4
Update .NET version to 8.0 & lang version to 12
Sep 23, 2025
1e25cc5
Use explicit public access modifier in C# code
aaronfranke Jul 22, 2025
e00a639
C#: Ensure mono editor supports Visual Studio 2026
Repiteo Nov 19, 2025
e321839
Fix dotnet class lookup returning modified names instead of engine names
kevinlam508 Oct 25, 2025
c9bb73f
Do not attempt deleting local cache in `Resource::_teardown_duplicate…
bruvzg Nov 26, 2025
45d8453
Round values after renormalization when generating mipmaps.
blueskythlikesclouds Oct 20, 2025
c0370f5
Image: Fix normalization of mipmaps for half and float formats
BlueCube3310 Sep 7, 2025
211f5f0
main.cpp: fix typo in gpu-profile CLI argument
gg-yb Oct 28, 2025
b5e3f80
Fix duplicating node references of custom node type properties
kevinlam508 Oct 27, 2025
6787fb0
Fix duplicate minus in print output.
bruvzg Sep 9, 2025
c1bcd5f
load_threaded_get doesn't return null resources when used with CACHE_…
ed-megacrit Oct 7, 2025
95e833a
Ensure all MovieWriter frames have the same resolution as the first f…
Calinou Jul 24, 2025
086a7f8
Improve determinism of UIDs
KoBeWi Oct 20, 2025
32ebcd8
Fix file duplication making random UID
KoBeWi Oct 24, 2025
1e0f3fc
LSP: Fix goto native declaration
HolonProduction Oct 10, 2025
e6721b7
Fix verbose running message
KoBeWi Oct 24, 2025
620a4da
Fix incorrect margins in `ScrollContainer` with focus border enabled
YeldhamDev Oct 7, 2025
774a817
Save editor settings when modified from code
KoBeWi Oct 18, 2025
64754db
[TextServer] Do not add extra spacing to zero-width glyphs.
bruvzg Sep 8, 2025
a974dc0
[TextServer] Fix range for zero-width glyphs extra spacing.
bruvzg Oct 23, 2025
f9c37cb
Separate branching ping-pong time and delta
TokageItLab Oct 26, 2025
e9a6dec
Fix Input.is_joy_known response for SDL joypads
JestemStefan Oct 11, 2025
5f95c7c
Changed TileSetScenesCollectionSource raw pointers in the TileSet edi…
FantasmaGolicon Nov 13, 2025
9e81d61
[TextServer] Do not add empty lines if space trimming flag is set.
bruvzg Oct 20, 2025
5e4dd9b
[TextServer] Fix line wrapping underflow.
bruvzg Dec 19, 2025
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
32 changes: 0 additions & 32 deletions .github/workflows/cache_cleanup.yml

This file was deleted.

16 changes: 8 additions & 8 deletions core/input/input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -656,10 +656,16 @@ void Input::joy_connection_changed(int p_idx, bool p_connected, const String &p_
int mapping = fallback_mapping;
// Bypass the mapping system if the joypad's mapping is already handled by its driver
// (for example, the SDL joypad driver).
if (!p_joypad_info.get("mapping_handled", false)) {
if (p_joypad_info.get("mapping_handled", false)) {
js.is_known = true;
} else {
for (int i = 0; i < map_db.size(); i++) {
if (js.uid == map_db[i].uid) {
mapping = i;
if (mapping != fallback_mapping) {
js.is_known = true;
}
break;
}
}
}
Expand Down Expand Up @@ -1860,13 +1866,7 @@ void Input::set_fallback_mapping(const String &p_guid) {

//platforms that use the remapping system can override and call to these ones
bool Input::is_joy_known(int p_device) {
if (joy_names.has(p_device)) {
int mapping = joy_names[p_device].mapping;
if (mapping != -1 && mapping != fallback_mapping) {
return true;
}
}
return false;
return joy_names.has(p_device) && joy_names[p_device].is_known;
}

String Input::get_joy_guid(int p_device) const {
Expand Down
1 change: 1 addition & 0 deletions core/input/input.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ class Input : public Object {
StringName name;
StringName uid;
bool connected = false;
bool is_known = false;
bool last_buttons[(size_t)JoyButton::MAX] = { false };
float last_axis[(size_t)JoyAxis::MAX] = { 0.0f };
HatMask last_hat = HatMask::CENTER;
Expand Down
14 changes: 11 additions & 3 deletions core/io/image.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4230,22 +4230,30 @@ void Image::renormalize_uint8(uint8_t *p_rgb) {
n += Vector3(1, 1, 1);
n *= 0.5;
n *= 255;
p_rgb[0] = CLAMP(int(n.x), 0, 255);
p_rgb[1] = CLAMP(int(n.y), 0, 255);
p_rgb[2] = CLAMP(int(n.z), 0, 255);
p_rgb[0] = CLAMP(int(Math::round(n.x)), 0, 255);
p_rgb[1] = CLAMP(int(Math::round(n.y)), 0, 255);
p_rgb[2] = CLAMP(int(Math::round(n.z)), 0, 255);
}

void Image::renormalize_float(float *p_rgb) {
Vector3 n(p_rgb[0], p_rgb[1], p_rgb[2]);
n *= 2.0;
n -= Vector3(1, 1, 1);
n.normalize();
n += Vector3(1, 1, 1);
n *= 0.5;
p_rgb[0] = n.x;
p_rgb[1] = n.y;
p_rgb[2] = n.z;
}

void Image::renormalize_half(uint16_t *p_rgb) {
Vector3 n(Math::half_to_float(p_rgb[0]), Math::half_to_float(p_rgb[1]), Math::half_to_float(p_rgb[2]));
n *= 2.0;
n -= Vector3(1, 1, 1);
n.normalize();
n += Vector3(1, 1, 1);
n *= 0.5;
p_rgb[0] = Math::make_half_float(n.x);
p_rgb[1] = Math::make_half_float(n.y);
p_rgb[2] = Math::make_half_float(n.z);
Expand Down
13 changes: 11 additions & 2 deletions core/io/resource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -368,11 +368,14 @@ Ref<Resource> Resource::_duplicate(const DuplicateParams &p_params) const {
ERR_FAIL_COND_V_MSG(p_params.local_scene && p_params.subres_mode != RESOURCE_DEEP_DUPLICATE_MAX, Ref<Resource>(), "Duplication for local-to-scene can't specify a deep duplicate mode.");

DuplicateRemapCacheT *remap_cache_backup = thread_duplicate_remap_cache;
bool remap_cache_needs_deallocation_backup = thread_duplicate_remap_cache_needs_deallocation;

// These are for avoiding potential duplicates that can happen in custom code
// from participating in the same duplication session (remap cache).
#define BEFORE_USER_CODE thread_duplicate_remap_cache = nullptr;
#define AFTER_USER_CODE thread_duplicate_remap_cache = remap_cache_backup;
#define AFTER_USER_CODE \
thread_duplicate_remap_cache = remap_cache_backup; \
thread_duplicate_remap_cache_needs_deallocation = remap_cache_needs_deallocation_backup;

List<PropertyInfo> plist;
get_property_list(&plist);
Expand Down Expand Up @@ -434,14 +437,17 @@ Ref<Resource> Resource::duplicate_for_local_scene(Node *p_for_scene, DuplicateRe
#endif

DuplicateRemapCacheT *remap_cache_backup = thread_duplicate_remap_cache;
bool remap_cache_needs_deallocation_backup = thread_duplicate_remap_cache_needs_deallocation;
thread_duplicate_remap_cache = &p_remap_cache;
thread_duplicate_remap_cache_needs_deallocation = false;

DuplicateParams params;
params.deep = true;
params.local_scene = p_for_scene;
const Ref<Resource> &dupe = _duplicate(params);

thread_duplicate_remap_cache = remap_cache_backup;
thread_duplicate_remap_cache_needs_deallocation = remap_cache_needs_deallocation_backup;

return dupe;
}
Expand Down Expand Up @@ -504,6 +510,7 @@ Ref<Resource> Resource::duplicate(bool p_deep) const {
bool started_session = false;
if (!thread_duplicate_remap_cache) {
thread_duplicate_remap_cache = &remap_cache;
thread_duplicate_remap_cache_needs_deallocation = false;
started_session = true;
}

Expand All @@ -526,6 +533,7 @@ Ref<Resource> Resource::duplicate_deep(ResourceDeepDuplicateMode p_deep_subresou
bool started_session = false;
if (!thread_duplicate_remap_cache) {
thread_duplicate_remap_cache = &remap_cache;
thread_duplicate_remap_cache_needs_deallocation = false;
started_session = true;
}

Expand Down Expand Up @@ -571,6 +579,7 @@ Ref<Resource> Resource::_duplicate_from_variant(bool p_deep, ResourceDeepDuplica
}
} else {
thread_duplicate_remap_cache = memnew(DuplicateRemapCacheT);
thread_duplicate_remap_cache_needs_deallocation = true;
}

DuplicateParams params;
Expand All @@ -583,7 +592,7 @@ Ref<Resource> Resource::_duplicate_from_variant(bool p_deep, ResourceDeepDuplica
}

void Resource::_teardown_duplicate_from_variant() {
if (thread_duplicate_remap_cache) {
if (thread_duplicate_remap_cache && thread_duplicate_remap_cache_needs_deallocation) {
memdelete(thread_duplicate_remap_cache);
thread_duplicate_remap_cache = nullptr;
}
Expand Down
1 change: 1 addition & 0 deletions core/io/resource.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ class Resource : public RefCounted {

using DuplicateRemapCacheT = HashMap<Ref<Resource>, Ref<Resource>>;
static thread_local inline DuplicateRemapCacheT *thread_duplicate_remap_cache = nullptr;
static thread_local inline bool thread_duplicate_remap_cache_needs_deallocation = true;

Variant _duplicate_recursive(const Variant &p_variant, const DuplicateParams &p_params, uint32_t p_usage = 0) const;
void _find_sub_resources(const Variant &p_variant, HashSet<Ref<Resource>> &p_resources_found);
Expand Down
36 changes: 29 additions & 7 deletions core/io/resource_loader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -697,21 +697,28 @@ ResourceLoader::ThreadLoadStatus ResourceLoader::load_threaded_get_status(const
}

String local_path = _validate_local_path(p_path);
ERR_FAIL_COND_V_MSG(!thread_load_tasks.has(local_path), THREAD_LOAD_INVALID_RESOURCE, "Bug in ResourceLoader logic, please report.");
LoadToken *load_token = user_load_tokens[p_path];
ThreadLoadTask *load_task_ptr;

if (load_token->task_if_unregistered) {
load_task_ptr = load_token->task_if_unregistered;
} else {
ERR_FAIL_COND_V_MSG(!thread_load_tasks.has(local_path), THREAD_LOAD_INVALID_RESOURCE, "Bug in ResourceLoader logic, please report.");
load_task_ptr = &thread_load_tasks[local_path];
}

ThreadLoadTask &load_task = thread_load_tasks[local_path];
status = load_task.status;
status = load_task_ptr->status;
if (r_progress) {
*r_progress = _dependency_get_progress(local_path);
}

// Support userland polling in a loop on the main thread.
if (Thread::is_main_thread() && status == THREAD_LOAD_IN_PROGRESS) {
uint64_t frame = Engine::get_singleton()->get_process_frames();
if (frame == load_task.last_progress_check_main_thread_frame) {
if (frame == load_task_ptr->last_progress_check_main_thread_frame) {
ensure_progress = true;
} else {
load_task.last_progress_check_main_thread_frame = frame;
load_task_ptr->last_progress_check_main_thread_frame = frame;
}
}
}
Expand Down Expand Up @@ -745,8 +752,23 @@ Ref<Resource> ResourceLoader::load_threaded_get(const String &p_path, Error *r_e

// Support userland requesting on the main thread before the load is reported to be complete.
if (Thread::is_main_thread() && !load_token->local_path.is_empty()) {
const ThreadLoadTask &load_task = thread_load_tasks[load_token->local_path];
while (load_task.status == THREAD_LOAD_IN_PROGRESS) {
ThreadLoadTask *load_task_ptr;

if (load_token->task_if_unregistered) {
load_task_ptr = load_token->task_if_unregistered;
} else {
if (!thread_load_tasks.has(load_token->local_path)) {
print_error("Bug in ResourceLoader logic, please report.");
if (r_error) {
*r_error = ERR_BUG;
}
return Ref<Resource>();
}

load_task_ptr = &thread_load_tasks[load_token->local_path];
}

while (load_task_ptr->status == THREAD_LOAD_IN_PROGRESS) {
thread_load_lock.temp_unlock();
bool exit = !_ensure_load_progress();
OS::get_singleton()->delay_usec(1000);
Expand Down
5 changes: 4 additions & 1 deletion core/io/resource_uid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,10 @@ ResourceUID::ID ResourceUID::create_id_for_path(const String &p_path) {
RandomPCG rng;

const String project_name = GLOBAL_GET("application/config/name");
rng.seed(project_name.hash64() * p_path.hash64() * FileAccess::get_md5(p_path).hash64());
// Use lowercase file name as random seed.
// This ensures that case differences don't cause UIDs to shift on case-insensitive filesystems. The downside is that identical files with different case
// (but otherwise identical name) will run into a hash collision, but this is a very rare scenario.
rng.seed(project_name.hash64() * p_path.to_lower().hash64() * FileAccess::get_md5(p_path).hash64());

while (true) {
int64_t num1 = rng.rand();
Expand Down
6 changes: 5 additions & 1 deletion core/string/ustring.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5524,7 +5524,11 @@ String String::sprintf(const Array &values, bool *error) const {
// Get basic number.
String str;
if (!as_unsigned) {
str = String::num_int64(Math::abs(value), base, capitalize);
if (value == INT64_MIN) { // INT64_MIN can't be represented as positive value.
str = String::num_int64(value, base, capitalize).trim_prefix("-");
} else {
str = String::num_int64(Math::abs(value), base, capitalize);
}
} else {
uint64_t uvalue = *((uint64_t *)&value);
// In unsigned hex, if the value fits in 32 bits, trim it down to that.
Expand Down
1 change: 1 addition & 0 deletions doc/classes/EditorSettings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
<description>
Object that holds the project-independent editor settings. These settings are generally visible in the [b]Editor &gt; Editor Settings[/b] menu.
Property names use slash delimiters to distinguish sections. Setting values can be of any [Variant] type. It's recommended to use [code]snake_case[/code] for editor settings to be consistent with the Godot editor itself.
Editor settings are saved automatically when changed.
Accessing the settings can be done using the following methods, such as:
[codeblocks]
[gdscript]
Expand Down
1 change: 1 addition & 0 deletions drivers/sdl/SDL_build_config_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
#define SDL_PLATFORM_UNIX 1

#define HAVE_STDIO_H 1
#define HAVE_LIBC 1
#define HAVE_LINUX_INPUT_H 1
#define HAVE_POLL 1

Expand Down
3 changes: 2 additions & 1 deletion drivers/sdl/joypad_sdl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,8 @@ void JoypadSDL::process_events() {
sdl_instance_id_to_joypad_id.insert(sdl_event.jdevice.which, joy_id);

Dictionary joypad_info;
joypad_info["mapping_handled"] = true; // Skip Godot's mapping system because SDL already handles the joypad's mapping.
// Skip Godot's mapping system if SDL already handles the joypad's mapping.
joypad_info["mapping_handled"] = SDL_IsGamepad(sdl_event.jdevice.which);
joypad_info["raw_name"] = String(SDL_GetJoystickName(joy));
joypad_info["vendor_id"] = itos(SDL_GetJoystickVendor(joy));
joypad_info["product_id"] = itos(SDL_GetJoystickProduct(joy));
Expand Down
2 changes: 1 addition & 1 deletion editor/file_system/editor_file_system.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3086,7 +3086,7 @@ Error EditorFileSystem::_copy_file(const String &p_from, const String &p_to) {
}

// Roll a new uid for this copied .import file to avoid conflict.
ResourceUID::ID res_uid = ResourceUID::get_singleton()->create_id();
ResourceUID::ID res_uid = ResourceUID::get_singleton()->create_id_for_path(p_to);

// Save the new .import file
Ref<ConfigFile> cfg;
Expand Down
6 changes: 4 additions & 2 deletions editor/run/editor_run.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,10 +167,12 @@ Error EditorRun::run(const String &p_scene, const String &p_write_movie, const V
}

if (OS::get_singleton()->is_stdout_verbose()) {
print_line(vformat("Running: %s", exec));
PackedStringArray output;
output.append(vformat("Running: %s", exec));
for (const String &E : instance_args) {
print_line(" %s", E);
output.append(E);
}
print_line(String(" ").join(output));
}

OS::ProcessID pid = 0;
Expand Down
Loading