mirror of
https://github.com/4ian/GDevelop.git
synced 2025-10-15 10:19:04 +00:00

* This action allow to wait for a few seconds before continuing to run the next actions and sub-events. * It is perfect to create cut scenes, advanced logic or just run things progressively without relying on timers. In a lot of cases, it's simpler and faster to use this new action. * The action remember the picked objects: it works like an usual event, but run the actions (and sub-events) a bit later in time. While the action wait, other events continue to run as usual. * Thanks to @arthuro555 for the ground work and follow up on this new feature. Only show the rest in developer changelog: * Add support for asynchronous actions (including for objects). * Add exhaustive test cases for asynchronous actions. Co-authored-by: Arthur Pacaud <arthur.pacaud@hotmail.fr>
153 lines
5.7 KiB
C++
153 lines
5.7 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 "GDCore/Events/CodeGeneration/EventsCodeGenerationContext.h"
|
|
|
|
#include <set>
|
|
|
|
#include "GDCore/CommonTools.h"
|
|
#include "GDCore/Events/CodeGeneration/EventsCodeGenerator.h"
|
|
#include "GDCore/Events/Tools/EventsCodeNameMangler.h"
|
|
|
|
using namespace std;
|
|
|
|
namespace gd {
|
|
|
|
void EventsCodeGenerationContext::InheritsFrom(
|
|
EventsCodeGenerationContext& parent_) {
|
|
parent = &parent_;
|
|
|
|
// Objects lists declared by parent became "already declared" in the child
|
|
// context.
|
|
alreadyDeclaredObjectsLists = parent_.alreadyDeclaredObjectsLists;
|
|
std::copy(parent_.objectsListsToBeDeclared.begin(),
|
|
parent_.objectsListsToBeDeclared.end(),
|
|
std::inserter(alreadyDeclaredObjectsLists,
|
|
alreadyDeclaredObjectsLists.begin()));
|
|
std::copy(parent_.objectsListsOrEmptyToBeDeclared.begin(),
|
|
parent_.objectsListsOrEmptyToBeDeclared.end(),
|
|
std::inserter(alreadyDeclaredObjectsLists,
|
|
alreadyDeclaredObjectsLists.begin()));
|
|
std::copy(parent_.emptyObjectsListsToBeDeclared.begin(),
|
|
parent_.emptyObjectsListsToBeDeclared.end(),
|
|
std::inserter(alreadyDeclaredObjectsLists,
|
|
alreadyDeclaredObjectsLists.begin()));
|
|
|
|
nearestAsyncParent = parent_.IsAsyncCallback() ? &parent_ : parent_.nearestAsyncParent;
|
|
asyncDepth = parent_.asyncDepth;
|
|
depthOfLastUse = parent_.depthOfLastUse;
|
|
customConditionDepth = parent_.customConditionDepth;
|
|
contextDepth = parent_.GetContextDepth() + 1;
|
|
if (parent_.maxDepthLevel) {
|
|
maxDepthLevel = parent_.maxDepthLevel;
|
|
*maxDepthLevel = std::max(*maxDepthLevel, contextDepth);
|
|
}
|
|
}
|
|
|
|
void EventsCodeGenerationContext::InheritsAsAsyncCallbackFrom(
|
|
EventsCodeGenerationContext& parent_) {
|
|
// Increasing the async depth is enough to mark the context as an async callback.
|
|
InheritsFrom(parent_);
|
|
asyncDepth = parent_.asyncDepth + 1;
|
|
}
|
|
|
|
void EventsCodeGenerationContext::Reuse(
|
|
EventsCodeGenerationContext& parent_) {
|
|
InheritsFrom(parent_);
|
|
if (parent_.CanReuse())
|
|
contextDepth = parent_.GetContextDepth(); // Keep same context depth
|
|
}
|
|
|
|
void EventsCodeGenerationContext::NotifyAsyncParentsAboutDeclaredObject(const gd::String& objectName) {
|
|
gd::EventsCodeGenerationContext* asyncContext = IsAsyncCallback() ? this : nearestAsyncParent;
|
|
for (;
|
|
asyncContext != nullptr;
|
|
asyncContext = asyncContext->parent->nearestAsyncParent)
|
|
asyncContext->allObjectsListToBeDeclaredAcrossChildren.insert(objectName);
|
|
}
|
|
|
|
void EventsCodeGenerationContext::ObjectsListNeeded(
|
|
const gd::String& objectName) {
|
|
if (!IsToBeDeclared(objectName)) {
|
|
objectsListsToBeDeclared.insert(objectName);
|
|
|
|
if (IsInsideAsync()) {
|
|
NotifyAsyncParentsAboutDeclaredObject(objectName);
|
|
}
|
|
}
|
|
|
|
depthOfLastUse[objectName] = GetContextDepth();
|
|
}
|
|
|
|
void EventsCodeGenerationContext::ObjectsListNeededOrEmptyIfJustDeclared(
|
|
const gd::String& objectName) {
|
|
if (!IsToBeDeclared(objectName)) {
|
|
objectsListsOrEmptyToBeDeclared.insert(objectName);
|
|
|
|
if (IsInsideAsync()) {
|
|
NotifyAsyncParentsAboutDeclaredObject(objectName);
|
|
}
|
|
}
|
|
|
|
depthOfLastUse[objectName] = GetContextDepth();
|
|
}
|
|
|
|
void EventsCodeGenerationContext::EmptyObjectsListNeeded(
|
|
const gd::String& objectName) {
|
|
if (!IsToBeDeclared(objectName)) {
|
|
emptyObjectsListsToBeDeclared.insert(objectName);
|
|
}
|
|
|
|
depthOfLastUse[objectName] = GetContextDepth();
|
|
}
|
|
|
|
std::set<gd::String> EventsCodeGenerationContext::GetAllObjectsToBeDeclared()
|
|
const {
|
|
std::set<gd::String> allObjectListsToBeDeclared(
|
|
objectsListsToBeDeclared.begin(), objectsListsToBeDeclared.end());
|
|
allObjectListsToBeDeclared.insert(objectsListsOrEmptyToBeDeclared.begin(),
|
|
objectsListsOrEmptyToBeDeclared.end());
|
|
allObjectListsToBeDeclared.insert(emptyObjectsListsToBeDeclared.begin(),
|
|
emptyObjectsListsToBeDeclared.end());
|
|
|
|
return allObjectListsToBeDeclared;
|
|
}
|
|
|
|
unsigned int EventsCodeGenerationContext::GetLastDepthObjectListWasNeeded(
|
|
const gd::String& name) const {
|
|
if (depthOfLastUse.count(name) != 0) return depthOfLastUse.find(name)->second;
|
|
|
|
std::cout << "WARNING: During code generation, the last depth of an object "
|
|
"list was 0."
|
|
<< std::endl;
|
|
return 0;
|
|
}
|
|
|
|
bool EventsCodeGenerationContext::IsSameObjectsList(
|
|
const gd::String& objectName,
|
|
const EventsCodeGenerationContext& otherContext) const {
|
|
return GetLastDepthObjectListWasNeeded(objectName) ==
|
|
otherContext.GetLastDepthObjectListWasNeeded(objectName);
|
|
}
|
|
|
|
bool EventsCodeGenerationContext::ShouldUseAsyncObjectsList(
|
|
const gd::String& objectName) const {
|
|
if (!IsInsideAsync()) return false;
|
|
|
|
// Check if the objects list was used after (or in) the nearest async callback context.
|
|
const gd::EventsCodeGenerationContext* asyncContext = IsAsyncCallback() ? this : nearestAsyncParent;
|
|
if (parent->GetLastDepthObjectListWasNeeded(objectName) >= asyncContext->GetContextDepth()) {
|
|
// The object was used in a context after (or in) the nearest async parent context, so we're not getting it from the
|
|
// async object lists (it was already gotten from there in this previous context).
|
|
return false;
|
|
}
|
|
|
|
// If the objects list is declared in a parent of the nearest async context, it means
|
|
// the async context had to use an async objects list to access it.
|
|
return asyncContext->ObjectAlreadyDeclaredByParents(objectName);
|
|
};
|
|
|
|
} // namespace gd
|