Files
GDevelop/Core/GDCore/Events/Builtin/LinkEvent.cpp

160 lines
6.0 KiB
C++

/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#include <fstream>
#include <iostream>
#include "GDCore/CommonTools.h"
#include "GDCore/Events/Builtin/GroupEvent.h"
#include "GDCore/Events/Builtin/LinkEvent.h"
#include "GDCore/Events/CodeGeneration/EventsCodeGenerationContext.h"
#include "GDCore/Events/CodeGeneration/EventsCodeGenerator.h"
#include "GDCore/Events/Tools/EventsCodeNameMangler.h"
#include "GDCore/Project/ExternalEvents.h"
#include "GDCore/Project/Layout.h"
#include "GDCore/Project/Object.h"
#include "GDCore/Project/Project.h"
#include "GDCore/Serialization/SerializerElement.h"
using namespace std;
namespace gd {
const EventsList* LinkEvent::GetLinkedEvents(const gd::Project& project) const {
const EventsList* events = nullptr;
if (project.HasExternalEventsNamed(GetTarget())) {
const gd::ExternalEvents& linkedExternalEvents = project.GetExternalEvents(GetTarget());
events = &linkedExternalEvents.GetEvents();
} else if (project.HasLayoutNamed(GetTarget())) {
const gd::Layout& linkedLayout = project.GetLayout(GetTarget());
events = &linkedLayout.GetEvents();
}
// If the link only includes an events group, search it inside the
// layout/external events
if (events != nullptr && includeConfig == INCLUDE_EVENTS_GROUP) {
std::size_t i = 0;
std::size_t eventsCount = events->GetEventsCount();
for (; i < eventsCount; ++i) {
std::shared_ptr<const GroupEvent> groupEvent =
std::dynamic_pointer_cast<const GroupEvent>(
events->GetEventSmartPtr(i));
if (groupEvent && groupEvent->GetName() == eventsGroupName) {
// Get its sub-events
events = &groupEvent->GetSubEvents();
break;
}
}
if (i >= eventsCount) // We didn't find the events group, return nullptr
events = nullptr;
}
return events;
}
void LinkEvent::ReplaceLinkByLinkedEvents(
const gd::Project& project,
EventsList& eventList,
std::size_t indexOfTheEventInThisList) {
linkWasInvalid = false;
// Finding what to link to.
const EventsList* eventsToInclude = GetLinkedEvents(project);
if (eventsToInclude != NULL) {
std::size_t firstEvent =
includeConfig == INCLUDE_BY_INDEX ? GetIncludeStart() : 0;
std::size_t lastEvent = includeConfig == INCLUDE_BY_INDEX
? GetIncludeEnd()
: eventsToInclude->size() - 1;
// Check bounds
if (firstEvent >= eventsToInclude->size()) {
std::cout << "Unable to get events from a link ( Invalid start )"
<< std::endl;
linkWasInvalid = true;
return;
}
if (lastEvent >= eventsToInclude->size()) {
std::cout << "Unable to get events from a link ( Invalid end )"
<< std::endl;
linkWasInvalid = true;
return;
}
if (firstEvent > lastEvent) {
std::cout << "Unable to get events from a link ( End is before start )"
<< std::endl;
linkWasInvalid = true;
return;
}
// Insert an empty event to replace the link event ( we'll delete the link
// event at the end ) ( If we just erase the link event without adding a
// blank event to replace it, the first event inserted by the link will not
// be preprocessed ( and it can be annoying if it require preprocessing,
// such as another link event ). )
gd::EmptyEvent emptyEvent;
eventList.InsertEvent(emptyEvent, indexOfTheEventInThisList);
eventList.InsertEvents(
*eventsToInclude, firstEvent, lastEvent, indexOfTheEventInThisList + 1);
// Delete the link event ( which is now at the end of the list of events
// we've just inserted )
eventList.RemoveEvent(indexOfTheEventInThisList + 1 +
static_cast<unsigned>(lastEvent - firstEvent) + 1);
} else {
std::cout << "Unable to get events from a link." << std::endl;
linkWasInvalid = true;
// Delete the link event
eventList.RemoveEvent(indexOfTheEventInThisList);
return;
}
}
LinkEvent::~LinkEvent() {}
void LinkEvent::SerializeTo(SerializerElement& element) const {
SerializerElement& includeElement = element.AddChild("include").SetAttribute(
"includeConfig", static_cast<int>(GetIncludeConfig()));
if (GetIncludeConfig() == INCLUDE_EVENTS_GROUP) {
includeElement.SetAttribute("eventsGroup", GetEventsGroupName());
} else if (GetIncludeConfig() == INCLUDE_BY_INDEX) {
includeElement.SetAttribute("start", static_cast<int>(GetIncludeStart()));
includeElement.SetAttribute("end", static_cast<int>(GetIncludeEnd()));
}
element.AddChild("target").SetValue(GetTarget());
}
void LinkEvent::UnserializeFrom(gd::Project& project,
const SerializerElement& element) {
SerializerElement& includeElement = element.GetChild("include", 0, "Limites");
SetTarget(element.GetChild("target", 0, "Scene").GetValue().GetString());
if (includeElement.HasAttribute("includeAll")) {
// Compatibility with GDevelop <= 4.0.92
if (includeElement.GetBoolAttribute("includeAll", true)) {
SetIncludeAllEvents();
} else {
SetIncludeStartAndEnd(includeElement.GetIntAttribute("start"),
includeElement.GetIntAttribute("end"));
}
} else {
// GDevelop > 4.0.92
IncludeConfig config = static_cast<IncludeConfig>(
includeElement.GetIntAttribute("includeConfig", 0));
if (config == INCLUDE_ALL)
SetIncludeAllEvents();
else if (config == INCLUDE_EVENTS_GROUP)
SetIncludeEventsGroup(includeElement.GetStringAttribute("eventsGroup"));
else if (config == INCLUDE_BY_INDEX)
SetIncludeStartAndEnd(includeElement.GetIntAttribute("start"),
includeElement.GetIntAttribute("end"));
}
}
} // namespace gd