diff --git a/bt/tasks/bt_task.cpp b/bt/tasks/bt_task.cpp index bbf5fa7a..c1707787 100644 --- a/bt/tasks/bt_task.cpp +++ b/bt/tasks/bt_task.cpp @@ -182,60 +182,47 @@ Ref BTTask::clone() const { // * Children are duplicated via children property. See _set_children(). + // * Make BBParam properties unique. + HashMap, Ref> duplicates; #ifdef LIMBOAI_MODULE - // Make BBParam properties unique. List props; inst->get_property_list(&props); - HashMap, Ref> duplicates; for (List::Element *E = props.front(); E; E = E->next()) { - if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) { - continue; - } - - Variant v = inst->get(E->get().name); - - if (v.is_ref_counted()) { - Ref ref = v; - if (ref.is_valid()) { - Ref res = ref; - if (res.is_valid() && res->is_class("BBParam")) { - if (!duplicates.has(res)) { - duplicates[res] = res->duplicate(); - } - res = duplicates[res]; - inst->set(E->get().name, res); - } - } - } - } + PropertyInfo prop = E->get(); #elif LIMBOAI_GDEXTENSION - // Make BBParam properties unique. TypedArray props = inst->get_property_list(); - HashMap, Ref> duplicates; for (int i = 0; i < props.size(); i++) { - Dictionary prop = props[i]; - if (!(int(prop["usage"]) & PROPERTY_USAGE_STORAGE)) { + PropertyInfo prop = PropertyInfo::from_dict(props[i]); +#endif + if (!(prop.usage & PROPERTY_USAGE_STORAGE)) { continue; } - StringName prop_name = prop["name"]; - Variant v = inst->get(prop_name); - - if (v.get_type() == Variant::OBJECT && int(prop["hint"]) == PROPERTY_HINT_RESOURCE_TYPE) { - Ref ref = v; - if (ref.is_valid()) { - Ref res = ref; - if (res.is_valid() && res->is_class("BBParam")) { - if (!duplicates.has(res)) { - duplicates[res] = res->duplicate(); + Variant prop_value = inst->get(prop.name); + Ref res = prop_value; + if (res.is_valid() && res->is_class("BBParam")) { + // Duplicate BBParam + if (!duplicates.has(res)) { + duplicates[res] = res->duplicate(); + } + res = duplicates[res]; + inst->set(prop.name, res); + } else if (prop_value.get_type() == Variant::ARRAY) { + // Duplicate BBParams instances inside an array. + // - This code doesn't handle arrays of arrays. + // - A partial workaround for: https://github.com/godotengine/godot/issues/74918 + // - We actually don't want to duplicate resources in clone() except for BBParam subtypes. + Array arr = prop_value; + if (arr.is_typed() && ClassDB::is_parent_class(arr.get_typed_class_name(), LW_NAME(BBParam))) { + for (int j = 0; j < arr.size(); j++) { + Ref bb_param = arr[j]; + if (bb_param.is_valid()) { + arr[j] = bb_param->duplicate(); } - res = duplicates[res]; - inst->set(prop_name, res); } } } } -#endif // LIMBOAI_MODULE & LIMBOAI_GDEXTENSION return inst; } diff --git a/util/limbo_string_names.cpp b/util/limbo_string_names.cpp index 97de2288..22f099a6 100644 --- a/util/limbo_string_names.cpp +++ b/util/limbo_string_names.cpp @@ -40,6 +40,7 @@ LimboStringNames::LimboStringNames() { add_child = SN("add_child"); add_child_at_index = SN("add_child_at_index"); AnimationFilter = SN("AnimationFilter"); + BBParam = SN("BBParam"); behavior_tree_finished = SN("behavior_tree_finished"); bold = SN("bold"); button_down = SN("button_down"); diff --git a/util/limbo_string_names.h b/util/limbo_string_names.h index d1f70365..f6eca760 100644 --- a/util/limbo_string_names.h +++ b/util/limbo_string_names.h @@ -56,6 +56,7 @@ class LimboStringNames { StringName add_child; StringName Add; StringName AnimationFilter; + StringName BBParam; StringName behavior_tree_finished; StringName bold; StringName button_down;