Repository: 4ian/GDevelop
File: Core/GDCore/Extensions/Metadata/ParameterMetadataTools.cpp (C++)

Code before:
      } else {
        outputObjectsContainer.InsertNewObject(
            project,
            parameter.GetExtraInfo(),
            objectName,
            outputObjectsContainer.GetObjectsCount());
      }

      // Memorize the last object name. By convention, parameters that require
      // an object (mainly, "objectvar" and "behavior") should be placed after
      // the object in the list of parameters (if possible, just after).
      // Search "lastObjectName" in the codebase for other place where this
      // convention is enforced.
      lastObjectName = objectName;
    } else if (gd::ParameterMetadata::IsBehavior(parameter.GetType())) {
      if (!lastObjectName.empty()) {
        if (outputObjectsContainer.HasObjectNamed(lastObjectName)) {
          const gd::String& behaviorName = parameter.GetName();
          const gd::String& behaviorType = parameter.GetExtraInfo();

          gd::Object& object = outputObjectsContainer.GetObject(lastObjectName);
          allObjectBehaviorNames[lastObjectName].insert(behaviorName);

          // Check if we can keep the existing behavior.
          if (object.HasBehaviorNamed(behaviorName)) {
            if (object.GetBehavior(behaviorName).GetTypeName() !=
                behaviorType) {
              // Behavior type has changed, remove it so it is re-created.
              object.RemoveBehavior(behaviorName);
            }
          }

          if (!object.HasBehaviorNamed(behaviorName)) {
            object.AddNewBehavior(
                project, parameter.GetExtraInfo(), behaviorName);
          }
        }
      }
    }
  }

  // Remove objects that are not in the parameters anymore.
  std::set<gd::String> objectNamesInContainer =
      outputObjectsContainer.GetAllObjectNames();
  for (const auto& objectName : objectNamesInContainer) {
    if (allObjectNames.find(objectName) == allObjectNames.end()) {
      outputObjectsContainer.RemoveObject(objectName);
    }
  }

  // Remove behaviors of objects that are not in the parameters anymore.

Review comment (suggestion):
I wonder if the name can be confusing because a free function could have an object parameter without object type and the following behavior parameters be some capabilities (default behavior). It also won't be "all" the behaviors of the actual objects.
I guess it's kind of the required behavior for objects passed in parameter, but "required" may be confusing as it's already used for behavior properties.

```suggestion
          objectAdditionnalBehaviorNames[lastObjectName].insert(behaviorName);
```


Code after:
        // are all present (and no more than required by the object type).
        // Non default behaviors coming from parameters will be added or removed later.
        project.EnsureObjectDefaultBehaviors(outputObjectsContainer.GetObject(objectName));
      } else {
        // Create a new object (and its default behaviors) if needed.
        outputObjectsContainer.InsertNewObject(
            project,
            objectType,
            objectName,
            outputObjectsContainer.GetObjectsCount());
      }

      // Memorize the last object name. By convention, parameters that require
      // an object (mainly, "objectvar" and "behavior") should be placed after
      // the object in the list of parameters (if possible, just after).
      // Search "lastObjectName" in the codebase for other place where this
      // convention is enforced.
      lastObjectName = objectName;
    } else if (gd::ParameterMetadata::IsBehavior(parameter.GetType())) {
      if (!lastObjectName.empty()) {
        if (outputObjectsContainer.HasObjectNamed(lastObjectName)) {
          const gd::String& behaviorName = parameter.GetName();
          const gd::String& behaviorType = parameter.GetExtraInfo();

          gd::Object& object = outputObjectsContainer.GetObject(lastObjectName);
          allObjectNonDefaultBehaviorNames[lastObjectName].insert(behaviorName);

          // Check if we can keep the existing behavior.
          if (object.HasBehaviorNamed(behaviorName)) {
            if (object.GetBehavior(behaviorName).GetTypeName() !=
                behaviorType) {
              // Behavior type has changed, remove it so it is re-created.
              object.RemoveBehavior(behaviorName);
            }
          }

          if (!object.HasBehaviorNamed(behaviorName)) {
            object.AddNewBehavior(
                project, parameter.GetExtraInfo(), behaviorName);
          }
        }
      }
    }
  }

  // Remove objects that are not in the parameters anymore.
  std::set<gd::String> objectNamesInContainer =
      outputObjectsContainer.GetAllObjectNames();
  for (const auto& objectName : objectNamesInContainer) {
    if (allObjectNames.find(objectName) == allObjectNames.end()) {
      outputObjectsContainer.RemoveObject(objectName);