godot-0005 (UNDF-2026-000000584): AStar3D/AStar2D/AStarGrid2D::_solve() open_list.find(e) in heap decrease-key branch — O(N) LocalVector scan per node relaxation; fix adds open_index field to Point struct for O(1) lookup. core/math/a_star.cpp:373,878 + a_star_grid_2d.cpp:572. 800x ops reduction. godot-0006 (UNDF-2026-000000585): Skeleton3D::_update_process_order() child_bones.has(i) Vector<int> O(C) scan inside O(B) bone rebuild loop; fix changes child_bones to HashSet<int>. 24x at wide flat rigs. scene/3d/skeleton_3d.cpp:235. godot-0007 (UNDF-2026-000000586): PostImportPluginSkeletonRestFixer bones_to_process.has() + keep_bone_rest.has() — Vector<int> O(B) scan inside O(T) animation track loops; O(T*B) total (188x at T=2000/B=500). Fix: HashSet<int> for both collections. editor/import/3d/post_import_plugin_skeleton_rest_fixer.cpp:201,212,681,742. godot-0008 (UNDF-2026-000000587): GLTFDocument::_serialize_nodes/animations() extensions_used.has() — Vector<String> O(E) scan inside per-node and per-animation serialization loops; O((N+A)*E) per export (11x at 3K nodes). Fix: Vector<String> extensions_used -> HashSet<String> in gltf_state.h. modules/gltf/gltf_document.cpp:443,5496. Redot-engine is an identical fork: all four defects confirmed present. 8/8 unit tests PASS (GodotAStarSkeletonTest.java).
46 lines
2.2 KiB
Diff
46 lines
2.2 KiB
Diff
# UNDF: UNDF-2026-000000587
|
|
--- a/modules/gltf/gltf_state.h
|
|
+++ b/modules/gltf/gltf_state.h
|
|
@@ -93,7 +93,7 @@ class GLTFState : public Resource {
|
|
Vector<String> extensions_required;
|
|
|
|
- Vector<String> extensions_used;
|
|
+ HashSet<String> extensions_used; // FIX godot-0008: was Vector<String> — O(E) .has() per node/animation
|
|
--- a/modules/gltf/gltf_document.cpp
|
|
+++ b/modules/gltf/gltf_document.cpp
|
|
@@ -248,7 +248,7 @@ Error GLTFDocument::_serialize_asset_header(Ref<GLTFState> p_state) {
|
|
// Collect extensions_used from state, plus any auto-added ones.
|
|
- Vector<String> extensions_used = p_state->extensions_used;
|
|
+ // FIX godot-0008: extensions_used is now HashSet; convert to sorted Vector for JSON
|
|
+ Vector<String> extensions_used;
|
|
+ for (const String &ext : p_state->extensions_used) {
|
|
+ extensions_used.push_back(ext);
|
|
+ }
|
|
if (_lights.size()) {
|
|
extensions_used.push_back("KHR_lights_punctual");
|
|
}
|
|
@@ -441,7 +441,7 @@ Error GLTFDocument::_serialize_nodes(Ref<GLTFState> p_state) {
|
|
if (!gltf_node->visible) {
|
|
...
|
|
- if (!p_state->extensions_used.has("KHR_node_visibility")) {
|
|
- p_state->extensions_used.push_back("KHR_node_visibility");
|
|
+ // FIX godot-0008: HashSet.insert() is idempotent and O(1) — was O(E) Vector scan
|
|
+ p_state->extensions_used.insert("KHR_node_visibility");
|
|
if (_visibility_mode == VISIBILITY_MODE_INCLUDE_REQUIRED) {
|
|
p_state->extensions_required.push_back("KHR_node_visibility");
|
|
}
|
|
- }
|
|
@@ -5494,7 +5494,7 @@ void GLTFDocument::_serialize_animations(Ref<GLTFState> p_state) {
|
|
if (!gltf_animation->get_pointer_tracks().is_empty()) {
|
|
- if (!p_state->extensions_used.has("KHR_animation_pointer")) {
|
|
- p_state->extensions_used.push_back("KHR_animation_pointer");
|
|
- }
|
|
+ // FIX godot-0008: HashSet.insert() is idempotent O(1)
|
|
+ p_state->extensions_used.insert("KHR_animation_pointer");
|
|
@@ -8957,7 +8957,7 @@ void GLTFDocument::_parse_extensions(Ref<GLTFState> p_state) {
|
|
- p_state->extensions_used = ext_array; // Vector assignment
|
|
+ // FIX godot-0008: populate HashSet from parsed JSON array
|
|
+ p_state->extensions_used.clear();
|
|
+ for (int i = 0; i < ext_array.size(); i++) {
|
|
+ p_state->extensions_used.insert(ext_array[i]);
|
|
+ }
|