Files
GDevelop/Core/GDCore/IDE/EventsFunctionTools.cpp
D8H d40e360b8a Add support for behaviors based on other behaviors ("behavior composition") (#2781)
* This allows [custom behaviors](http://wiki.compilgames.net/doku.php/gdevelop5/behaviors/events-based-behaviors), that you can create in your project or get from extensions, to require the presence of one or multiple other behaviors on an object.
  * This is an advanced feature that is helpful to create behaviors that are based on other. For example, a behavior "Platformer enemy" using the "Platformer object" behavior and adding specific actions, conditions and logic to make an enemy chase the player.
  * If you create a behavior and want to use this, just go to the properties of this behavior and add a new property. Choose the type "Required Behavior" for this property. You can then use this new behavior in the events of the behavior you just edited.
* To use a behavior based on another, you don't need to do anything special! Just add it to your object as usual: any missing behavior will be added to your object, so you can start using it immediately.
2021-09-06 19:51:42 +01:00

76 lines
3.0 KiB
C++

/*
* GDevelop Core
* Copyright 2008-present Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#include "EventsFunctionTools.h"
#include "GDCore/Events/Expression.h"
#include "GDCore/Extensions/Metadata/ParameterMetadataTools.h"
#include "GDCore/Project/EventsBasedBehavior.h"
#include "GDCore/Project/EventsFunction.h"
#include "GDCore/Project/Object.h"
#include "GDCore/Project/ObjectsContainer.h"
#include "GDCore/Project/Project.h"
#include "GDCore/String.h"
#include "GDCore/Tools/Log.h"
namespace gd {
void EventsFunctionTools::FreeEventsFunctionToObjectsContainer(
gd::Project& project,
const gd::EventsFunction& eventsFunction,
gd::ObjectsContainer& outputGlobalObjectsContainer,
gd::ObjectsContainer& outputObjectsContainer) {
// Functions don't have access to objects from the "outer" scope.
outputGlobalObjectsContainer.GetObjects().clear();
outputGlobalObjectsContainer.GetObjectGroups().Clear();
// Functions scope for objects is defined according
// to parameters
outputObjectsContainer.GetObjects().clear();
outputObjectsContainer.GetObjectGroups().Clear();
gd::ParameterMetadataTools::ParametersToObjectsContainer(
project, eventsFunction.GetParameters(), outputObjectsContainer);
outputObjectsContainer.GetObjectGroups() = eventsFunction.GetObjectGroups();
}
void EventsFunctionTools::BehaviorEventsFunctionToObjectsContainer(
gd::Project& project,
const gd::EventsBasedBehavior& eventsBasedBehavior,
const gd::EventsFunction& eventsFunction,
gd::ObjectsContainer& outputGlobalObjectsContainer,
gd::ObjectsContainer& outputObjectsContainer) {
// The context is build the same way as free function...
FreeEventsFunctionToObjectsContainer(project,
eventsFunction,
outputGlobalObjectsContainer,
outputObjectsContainer);
// ...and has an "Object" by convention...
if (!outputObjectsContainer.HasObjectNamed("Object")) {
gd::LogWarning("No \"Object\" in a function of an events based behavior: " +
eventsFunction.GetName() +
". This means this function is likely misconfigured (check "
"its parameters).");
return;
}
// ...with behaviors from properties.
gd::Object& thisObject = outputObjectsContainer.GetObject("Object");
for (size_t i = 0;
i < eventsBasedBehavior.GetPropertyDescriptors().GetCount();
i++) {
const NamedPropertyDescriptor& propertyDescriptor =
eventsBasedBehavior.GetPropertyDescriptors().Get(i);
const std::vector<gd::String>& extraInfo =
propertyDescriptor.GetExtraInfo();
if (propertyDescriptor.GetType() == "Behavior" && extraInfo.size() > 0) {
gd::String behaviorName = propertyDescriptor.GetName();
thisObject.AddNewBehavior(project, extraInfo.at(0), behaviorName);
}
}
}
} // namespace gd