Files
GDevelop/Core/GDCore/IDE/EventsFunctionTools.cpp
Florian Rival a51c223c9c Add experimental, work-in-progress visual editor for custom objects (aka "prefabs"/"templates") (#6699)
* Still to do: 
  * Properly handle effects (disable 3D effects) for layers
  * Handle hot reloading properly
  * Avoid duplicating the configuration of the custom object inside each object created from it. Instead, only store the modified values.
  * Add a "Extract as a custom object ("prefab")" when selecting instances in a scene.
  * Add a dialog to give choice between 2D or 3D object when creating one.
  * Make sure "behavior shared data" are properly handled (physics, pathfinding...)
  * Check if we need to give an expression to translate coordinates from the parent to the local custom object.
  * Ensure a deleted custom object does not break the editor

Co-authored-by: Davy Hélard <davy.helard@gmail.com>
2024-07-11 11:27:34 +02:00

123 lines
4.9 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/EventsBasedObject.h"
//#include "GDCore/Project/ObjectsContainer.h"
#include "GDCore/Project/EventsFunction.h"
#include "GDCore/Project/Object.h"
#include "GDCore/Project/Project.h"
#include "GDCore/String.h"
#include "GDCore/Tools/Log.h"
namespace gd {
void EventsFunctionTools::FreeEventsFunctionToObjectsContainer(
const gd::Project& project,
const gd::EventsFunctionsContainer& functionContainer,
const gd::EventsFunction& eventsFunction,
gd::ObjectsContainer& outputObjectsContainer) {
// Functions scope for objects is defined according
// to parameters
outputObjectsContainer.GetObjects().clear();
outputObjectsContainer.GetObjectGroups().Clear();
auto &parameters = eventsFunction.GetParametersForEvents(functionContainer);
gd::ParameterMetadataTools::ParametersToObjectsContainer(
project,
parameters,
outputObjectsContainer);
outputObjectsContainer.GetObjectGroups() = eventsFunction.GetObjectGroups();
}
void EventsFunctionTools::BehaviorEventsFunctionToObjectsContainer(
const gd::Project& project,
const gd::EventsBasedBehavior& eventsBasedBehavior,
const gd::EventsFunction& eventsFunction,
gd::ObjectsContainer& outputObjectsContainer) {
// The context is build the same way as free function...
FreeEventsFunctionToObjectsContainer(project,
eventsBasedBehavior.GetEventsFunctions(),
eventsFunction,
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);
}
}
}
void EventsFunctionTools::ObjectEventsFunctionToObjectsContainer(
const gd::Project& project,
const gd::EventsBasedObject& eventsBasedObject,
const gd::EventsFunction& eventsFunction,
gd::ObjectsContainer& outputObjectsContainer) {
// The context is build the same way as free function...
FreeEventsFunctionToObjectsContainer(project,
eventsBasedObject.GetEventsFunctions(),
eventsFunction,
outputObjectsContainer);
// TODO EBO Use a constant instead a hard coded value "Object".
// ...and has an "Object" by convention...
if (!outputObjectsContainer.HasObjectNamed("Object")) {
gd::LogWarning("No \"Object\" in a function of an events based object: " +
eventsFunction.GetName() +
". This means this function is likely misconfigured (check "
"its parameters).");
return;
}
if (eventsBasedObject.GetObjects().HasObjectNamed("Object")) {
gd::LogWarning("Child-objects can't be named Object because it's reserved"
"for the parent. ");
return;
}
gd::EventsFunctionTools::CopyEventsBasedObjectChildrenToObjectsContainer(
eventsBasedObject, outputObjectsContainer);
}
void EventsFunctionTools::CopyEventsBasedObjectChildrenToObjectsContainer(
const gd::EventsBasedObject& eventsBasedObject,
gd::ObjectsContainer& outputObjectsContainer) {
auto &children = eventsBasedObject.GetObjects().GetObjects();
for (auto &childObject : children) {
auto child = childObject.get();
outputObjectsContainer.InsertObject(
*child, outputObjectsContainer.GetObjectsCount());
}
auto &childrenGroups = eventsBasedObject.GetObjects().GetObjectGroups();
for (size_t index = 0; index < childrenGroups.Count(); ++index) {
auto &childGroup = childrenGroups.Get(index);
outputObjectsContainer.GetObjectGroups().Insert(
childGroup, outputObjectsContainer.GetObjectGroups().Count());
}
}
} // namespace gd