Duplicate BBParam instances inside arrays in `BTTask::clone()`

Fixes issue with `CallMethod` arguments being shared between tasks after duplication.
This commit is contained in:
Serhii Snitsaruk 2024-10-28 14:51:42 +01:00
parent 3b15abf2c9
commit d5bc62830a
No known key found for this signature in database
GPG Key ID: A965EF8799FFEC2D
3 changed files with 28 additions and 39 deletions

View File

@ -182,60 +182,47 @@ Ref<BTTask> BTTask::clone() const {
// * Children are duplicated via children property. See _set_children(). // * Children are duplicated via children property. See _set_children().
// * Make BBParam properties unique.
HashMap<Ref<Resource>, Ref<Resource>> duplicates;
#ifdef LIMBOAI_MODULE #ifdef LIMBOAI_MODULE
// Make BBParam properties unique.
List<PropertyInfo> props; List<PropertyInfo> props;
inst->get_property_list(&props); inst->get_property_list(&props);
HashMap<Ref<Resource>, Ref<Resource>> duplicates;
for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) { for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) { PropertyInfo prop = E->get();
continue;
}
Variant v = inst->get(E->get().name);
if (v.is_ref_counted()) {
Ref<RefCounted> ref = v;
if (ref.is_valid()) {
Ref<Resource> 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);
}
}
}
}
#elif LIMBOAI_GDEXTENSION #elif LIMBOAI_GDEXTENSION
// Make BBParam properties unique.
TypedArray<Dictionary> props = inst->get_property_list(); TypedArray<Dictionary> props = inst->get_property_list();
HashMap<Ref<Resource>, Ref<Resource>> duplicates;
for (int i = 0; i < props.size(); i++) { for (int i = 0; i < props.size(); i++) {
Dictionary prop = props[i]; PropertyInfo prop = PropertyInfo::from_dict(props[i]);
if (!(int(prop["usage"]) & PROPERTY_USAGE_STORAGE)) { #endif
if (!(prop.usage & PROPERTY_USAGE_STORAGE)) {
continue; continue;
} }
StringName prop_name = prop["name"]; Variant prop_value = inst->get(prop.name);
Variant v = inst->get(prop_name); Ref<Resource> res = prop_value;
if (v.get_type() == Variant::OBJECT && int(prop["hint"]) == PROPERTY_HINT_RESOURCE_TYPE) {
Ref<RefCounted> ref = v;
if (ref.is_valid()) {
Ref<Resource> res = ref;
if (res.is_valid() && res->is_class("BBParam")) { if (res.is_valid() && res->is_class("BBParam")) {
// Duplicate BBParam
if (!duplicates.has(res)) { if (!duplicates.has(res)) {
duplicates[res] = res->duplicate(); duplicates[res] = res->duplicate();
} }
res = duplicates[res]; res = duplicates[res];
inst->set(prop_name, 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<Resource> bb_param = arr[j];
if (bb_param.is_valid()) {
arr[j] = bb_param->duplicate();
}
} }
} }
} }
} }
#endif // LIMBOAI_MODULE & LIMBOAI_GDEXTENSION
return inst; return inst;
} }

View File

@ -40,6 +40,7 @@ LimboStringNames::LimboStringNames() {
add_child = SN("add_child"); add_child = SN("add_child");
add_child_at_index = SN("add_child_at_index"); add_child_at_index = SN("add_child_at_index");
AnimationFilter = SN("AnimationFilter"); AnimationFilter = SN("AnimationFilter");
BBParam = SN("BBParam");
behavior_tree_finished = SN("behavior_tree_finished"); behavior_tree_finished = SN("behavior_tree_finished");
bold = SN("bold"); bold = SN("bold");
button_down = SN("button_down"); button_down = SN("button_down");

View File

@ -56,6 +56,7 @@ public:
StringName add_child; StringName add_child;
StringName Add; StringName Add;
StringName AnimationFilter; StringName AnimationFilter;
StringName BBParam;
StringName behavior_tree_finished; StringName behavior_tree_finished;
StringName bold; StringName bold;
StringName button_down; StringName button_down;