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

- Variants allows to restyle custom objects - They can be customized with the graphical editor - The asset store will progressively use them notably for UI elements (buttons, sliders)
374 lines
15 KiB
C++
374 lines
15 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 "ProjectBrowserHelper.h"
|
|
|
|
#include "GDCore/IDE/Events/ArbitraryEventsWorker.h"
|
|
#include "GDCore/IDE/EventsFunctionTools.h"
|
|
#include "GDCore/IDE/Project/ArbitraryEventBasedBehaviorsWorker.h"
|
|
#include "GDCore/IDE/Project/ArbitraryEventsFunctionsWorker.h"
|
|
#include "GDCore/IDE/Project/ArbitraryObjectsWorker.h"
|
|
#include "GDCore/IDE/Project/ArbitraryBehaviorSharedDataWorker.h"
|
|
#include "GDCore/Project/EventsBasedBehavior.h"
|
|
#include "GDCore/Project/EventsBasedObject.h"
|
|
#include "GDCore/Project/EventsFunctionsExtension.h"
|
|
#include "GDCore/Project/ExternalEvents.h"
|
|
#include "GDCore/Project/Layout.h"
|
|
#include "GDCore/Project/PropertiesContainer.h"
|
|
#include "GDCore/Project/Project.h"
|
|
#include "GDCore/Project/ProjectScopedContainers.h"
|
|
#include "GDCore/String.h"
|
|
#include "GDCore/IDE/DependenciesAnalyzer.h"
|
|
|
|
namespace gd {
|
|
|
|
void ProjectBrowserHelper::ExposeProjectEvents(
|
|
gd::Project &project, gd::ArbitraryEventsWorker &worker) {
|
|
// See also gd::ResourceExposer::ExposeWholeProjectResources
|
|
// for a method that traverses the whole project (this time for resources).
|
|
|
|
ExposeProjectEventsWithoutExtensions(project, worker);
|
|
|
|
// Add events based extensions
|
|
for (std::size_t e = 0; e < project.GetEventsFunctionsExtensionsCount();
|
|
e++) {
|
|
auto &eventsFunctionsExtension = project.GetEventsFunctionsExtension(e);
|
|
ProjectBrowserHelper::ExposeEventsFunctionsExtensionEvents(project, eventsFunctionsExtension, worker);
|
|
}
|
|
}
|
|
|
|
void ProjectBrowserHelper::ExposeProjectEvents(
|
|
gd::Project &project, gd::ArbitraryEventsWorkerWithContext &worker) {
|
|
// See also gd::ResourceExposer::ExposeWholeProjectResources
|
|
// for a method that traverses the whole project (this time for resources)
|
|
// and ExposeProjectEffects (this time for effects).
|
|
|
|
ExposeProjectEventsWithoutExtensions(project, worker);
|
|
|
|
// Add events based extensions
|
|
for (std::size_t e = 0; e < project.GetEventsFunctionsExtensionsCount();
|
|
e++) {
|
|
auto &eventsFunctionsExtension = project.GetEventsFunctionsExtension(e);
|
|
ProjectBrowserHelper::ExposeEventsFunctionsExtensionEvents(project, eventsFunctionsExtension, worker);
|
|
}
|
|
}
|
|
|
|
void ProjectBrowserHelper::ExposeProjectEventsWithoutExtensions(
|
|
gd::Project& project, gd::ArbitraryEventsWorker& worker) {
|
|
// Add layouts events
|
|
for (std::size_t s = 0; s < project.GetLayoutsCount(); s++) {
|
|
worker.Launch(project.GetLayout(s).GetEvents());
|
|
}
|
|
// Add external events events
|
|
for (std::size_t s = 0; s < project.GetExternalEventsCount(); s++) {
|
|
worker.Launch(project.GetExternalEvents(s).GetEvents());
|
|
}
|
|
}
|
|
|
|
void ProjectBrowserHelper::ExposeProjectEventsWithoutExtensions(
|
|
gd::Project& project, gd::ArbitraryEventsWorkerWithContext& worker) {
|
|
// Add layouts events
|
|
for (std::size_t s = 0; s < project.GetLayoutsCount(); s++) {
|
|
auto &layout = project.GetLayout(s);
|
|
auto projectScopedContainers =
|
|
gd::ProjectScopedContainers::MakeNewProjectScopedContainersForProjectAndLayout(project, layout);
|
|
worker.Launch(layout.GetEvents(), projectScopedContainers);
|
|
}
|
|
// Add external events events
|
|
for (std::size_t s = 0; s < project.GetExternalEventsCount(); s++) {
|
|
const auto &externalEvents = project.GetExternalEvents(s);
|
|
const gd::String &associatedLayout = externalEvents.GetAssociatedLayout();
|
|
if (project.HasLayoutNamed(associatedLayout)) {
|
|
auto &layout = project.GetLayout(associatedLayout);
|
|
auto projectScopedContainers =
|
|
gd::ProjectScopedContainers::MakeNewProjectScopedContainersForProjectAndLayout(project, layout);
|
|
worker.Launch(project.GetExternalEvents(s).GetEvents(), projectScopedContainers);
|
|
}
|
|
}
|
|
}
|
|
|
|
void ProjectBrowserHelper::ExposeLayoutEventsAndExternalEvents(
|
|
gd::Project &project, gd::Layout &layout,
|
|
gd::ArbitraryEventsWorker &worker) {
|
|
|
|
// Add layouts events
|
|
worker.Launch(layout.GetEvents());
|
|
|
|
// Add external events events
|
|
for (std::size_t s = 0; s < project.GetExternalEventsCount(); s++) {
|
|
auto &externalEvents = project.GetExternalEvents(s);
|
|
if (externalEvents.GetAssociatedLayout() == layout.GetName()) {
|
|
worker.Launch(externalEvents.GetEvents());
|
|
}
|
|
}
|
|
}
|
|
|
|
void ProjectBrowserHelper::ExposeLayoutEventsAndExternalEvents(
|
|
gd::Project &project, gd::Layout &layout,
|
|
gd::ArbitraryEventsWorkerWithContext &worker) {
|
|
auto projectScopedContainers =
|
|
gd::ProjectScopedContainers::MakeNewProjectScopedContainersForProjectAndLayout(project, layout);
|
|
|
|
// Add layouts events
|
|
worker.Launch(layout.GetEvents(), projectScopedContainers);
|
|
|
|
// Add external events events
|
|
for (std::size_t s = 0; s < project.GetExternalEventsCount(); s++) {
|
|
auto &externalEvents = project.GetExternalEvents(s);
|
|
if (externalEvents.GetAssociatedLayout() == layout.GetName()) {
|
|
worker.Launch(externalEvents.GetEvents(), projectScopedContainers);
|
|
}
|
|
}
|
|
}
|
|
|
|
void ProjectBrowserHelper::ExposeLayoutEventsAndDependencies(
|
|
gd::Project &project, gd::Layout &layout,
|
|
gd::ArbitraryEventsWorker &worker) {
|
|
// Add layouts events
|
|
worker.Launch(layout.GetEvents());
|
|
|
|
DependenciesAnalyzer dependenciesAnalyzer(project, layout);
|
|
bool hasCircularDependencies = !dependenciesAnalyzer.Analyze();
|
|
if (hasCircularDependencies) {
|
|
// The analyzer stops when it finds circular dependencies so the dependencies are not complete.
|
|
// TODO Should the analyzer still continue to avoid side effect on thing that would not be code generation related?
|
|
// Maybe a boolean parameter should be added?
|
|
return;
|
|
}
|
|
for (const gd::String& externalEventName : dependenciesAnalyzer.GetExternalEventsDependencies()) {
|
|
gd::ExternalEvents& externalEvents = project.GetExternalEvents(externalEventName);
|
|
|
|
worker.Launch(externalEvents.GetEvents());
|
|
}
|
|
for (const gd::String& sceneName : dependenciesAnalyzer.GetScenesDependencies()) {
|
|
gd::Layout& dependencyLayout = project.GetLayout(sceneName);
|
|
|
|
worker.Launch(dependencyLayout.GetEvents());
|
|
}
|
|
}
|
|
|
|
void ProjectBrowserHelper::ExposeEventsFunctionsExtensionEvents(
|
|
gd::Project &project, const gd::EventsFunctionsExtension &eventsFunctionsExtension,
|
|
gd::ArbitraryEventsWorker &worker) {
|
|
// Add (free) events functions
|
|
for (auto &&eventsFunction :
|
|
eventsFunctionsExtension.GetEventsFunctions().GetInternalVector()) {
|
|
worker.Launch(eventsFunction->GetEvents());
|
|
}
|
|
|
|
// Add (behavior) events functions
|
|
for (auto &&eventsBasedBehavior :
|
|
eventsFunctionsExtension.GetEventsBasedBehaviors()
|
|
.GetInternalVector()) {
|
|
ExposeEventsBasedBehaviorEvents(project, *eventsBasedBehavior, worker);
|
|
}
|
|
|
|
// Add (object) events functions
|
|
for (auto &&eventsBasedObject :
|
|
eventsFunctionsExtension.GetEventsBasedObjects().GetInternalVector()) {
|
|
ExposeEventsBasedObjectEvents(project, *eventsBasedObject, worker);
|
|
}
|
|
}
|
|
|
|
void ProjectBrowserHelper::ExposeEventsFunctionsExtensionEvents(
|
|
gd::Project &project, const gd::EventsFunctionsExtension &eventsFunctionsExtension,
|
|
gd::ArbitraryEventsWorkerWithContext &worker) {
|
|
// Add (free) events functions
|
|
for (auto &&eventsFunction :
|
|
eventsFunctionsExtension.GetEventsFunctions().GetInternalVector()) {
|
|
gd::ObjectsContainer parameterObjectsContainer(
|
|
gd::ObjectsContainer::SourceType::Function);
|
|
gd::VariablesContainer parameterVariablesContainer(
|
|
gd::VariablesContainer::SourceType::Parameters);
|
|
gd::VariablesContainer propertyVariablesContainer(
|
|
gd::VariablesContainer::SourceType::Properties);
|
|
auto projectScopedContainers = gd::ProjectScopedContainers::
|
|
MakeNewProjectScopedContainersForFreeEventsFunction(
|
|
project, eventsFunctionsExtension, *eventsFunction,
|
|
parameterObjectsContainer, parameterVariablesContainer);
|
|
|
|
worker.Launch(eventsFunction->GetEvents(), projectScopedContainers);
|
|
}
|
|
|
|
// Add (behavior) events functions
|
|
for (auto &&eventsBasedBehavior :
|
|
eventsFunctionsExtension.GetEventsBasedBehaviors()
|
|
.GetInternalVector()) {
|
|
ExposeEventsBasedBehaviorEvents(project, eventsFunctionsExtension, *eventsBasedBehavior, worker);
|
|
}
|
|
|
|
// Add (object) events functions
|
|
for (auto &&eventsBasedObject :
|
|
eventsFunctionsExtension.GetEventsBasedObjects().GetInternalVector()) {
|
|
ExposeEventsBasedObjectEvents(project, eventsFunctionsExtension, *eventsBasedObject, worker);
|
|
}
|
|
}
|
|
|
|
void ProjectBrowserHelper::ExposeEventsBasedBehaviorEvents(
|
|
gd::Project &project, const gd::EventsBasedBehavior &eventsBasedBehavior,
|
|
gd::ArbitraryEventsWorker &worker) {
|
|
auto &behaviorEventsFunctions = eventsBasedBehavior.GetEventsFunctions();
|
|
for (auto &&eventsFunction : behaviorEventsFunctions.GetInternalVector()) {
|
|
worker.Launch(eventsFunction->GetEvents());
|
|
}
|
|
}
|
|
|
|
void ProjectBrowserHelper::ExposeEventsBasedBehaviorEvents(
|
|
gd::Project &project, const gd::EventsFunctionsExtension &eventsFunctionsExtension,
|
|
const gd::EventsBasedBehavior &eventsBasedBehavior,
|
|
gd::ArbitraryEventsWorkerWithContext &worker) {
|
|
gd::VariablesContainer propertyVariablesContainer(
|
|
gd::VariablesContainer::SourceType::Properties);
|
|
gd::ProjectBrowserHelper::ExposeEventsBasedBehaviorEvents(
|
|
project, eventsFunctionsExtension,
|
|
eventsBasedBehavior,
|
|
propertyVariablesContainer,
|
|
worker);
|
|
}
|
|
|
|
void ProjectBrowserHelper::ExposeEventsBasedBehaviorEvents(
|
|
gd::Project &project, const gd::EventsFunctionsExtension &eventsFunctionsExtension,
|
|
const gd::EventsBasedBehavior &eventsBasedBehavior,
|
|
gd::VariablesContainer &propertyVariablesContainer,
|
|
gd::ArbitraryEventsWorkerWithContext &worker) {
|
|
auto &behaviorEventsFunctions = eventsBasedBehavior.GetEventsFunctions();
|
|
for (auto &&eventsFunction : behaviorEventsFunctions.GetInternalVector()) {
|
|
|
|
gd::ObjectsContainer parameterObjectsContainers(
|
|
gd::ObjectsContainer::SourceType::Function);
|
|
gd::VariablesContainer parameterVariablesContainer(
|
|
gd::VariablesContainer::SourceType::Parameters);
|
|
auto projectScopedContainers = gd::ProjectScopedContainers::
|
|
MakeNewProjectScopedContainersForBehaviorEventsFunction(
|
|
project, eventsFunctionsExtension, eventsBasedBehavior,
|
|
*eventsFunction, parameterObjectsContainers,
|
|
parameterVariablesContainer, propertyVariablesContainer);
|
|
|
|
worker.Launch(eventsFunction->GetEvents(), projectScopedContainers);
|
|
}
|
|
}
|
|
|
|
void ProjectBrowserHelper::ExposeEventsBasedObjectEvents(
|
|
gd::Project &project, const gd::EventsBasedObject &eventsBasedObject,
|
|
gd::ArbitraryEventsWorker &worker) {
|
|
auto &objectEventsFunctions = eventsBasedObject.GetEventsFunctions();
|
|
for (auto &&eventsFunction : objectEventsFunctions.GetInternalVector()) {
|
|
worker.Launch(eventsFunction->GetEvents());
|
|
}
|
|
}
|
|
|
|
void ProjectBrowserHelper::ExposeEventsBasedObjectEvents(
|
|
gd::Project &project,
|
|
const gd::EventsFunctionsExtension &eventsFunctionsExtension,
|
|
const gd::EventsBasedObject &eventsBasedObject,
|
|
gd::ArbitraryEventsWorkerWithContext &worker) {
|
|
gd::VariablesContainer propertyVariablesContainer(
|
|
gd::VariablesContainer::SourceType::Properties);
|
|
gd::ProjectBrowserHelper::ExposeEventsBasedObjectEvents(
|
|
project, eventsFunctionsExtension, eventsBasedObject,
|
|
propertyVariablesContainer, worker);
|
|
}
|
|
|
|
void ProjectBrowserHelper::ExposeEventsBasedObjectEvents(
|
|
gd::Project &project,
|
|
const gd::EventsFunctionsExtension &eventsFunctionsExtension,
|
|
const gd::EventsBasedObject &eventsBasedObject,
|
|
gd::VariablesContainer &propertyVariablesContainer,
|
|
gd::ArbitraryEventsWorkerWithContext &worker) {
|
|
auto &objectEventsFunctions = eventsBasedObject.GetEventsFunctions();
|
|
for (auto &&eventsFunction : objectEventsFunctions.GetInternalVector()) {
|
|
|
|
gd::ObjectsContainer parameterObjectsContainers(
|
|
gd::ObjectsContainer::SourceType::Function);
|
|
gd::VariablesContainer parameterVariablesContainer(
|
|
gd::VariablesContainer::SourceType::Parameters);
|
|
auto projectScopedContainers = gd::ProjectScopedContainers::
|
|
MakeNewProjectScopedContainersForObjectEventsFunction(
|
|
project, eventsFunctionsExtension, eventsBasedObject,
|
|
*eventsFunction, parameterObjectsContainers,
|
|
parameterVariablesContainer, propertyVariablesContainer);
|
|
|
|
worker.Launch(eventsFunction->GetEvents(), projectScopedContainers);
|
|
}
|
|
}
|
|
|
|
void ProjectBrowserHelper::ExposeProjectObjects(
|
|
gd::Project &project, gd::ArbitraryObjectsWorker &worker) {
|
|
|
|
// Global objects
|
|
worker.Launch(project.GetObjects());
|
|
|
|
// Layout objects
|
|
for (size_t i = 0; i < project.GetLayoutsCount(); i++) {
|
|
gd::ProjectBrowserHelper::ExposeLayoutObjects(project.GetLayout(i), worker);
|
|
}
|
|
|
|
// Event based objects children
|
|
for (std::size_t e = 0; e < project.GetEventsFunctionsExtensionsCount();
|
|
e++) {
|
|
auto &eventsFunctionsExtension = project.GetEventsFunctionsExtension(e);
|
|
|
|
for (auto &&eventsBasedObjectUniquePtr :
|
|
eventsFunctionsExtension.GetEventsBasedObjects().GetInternalVector()) {
|
|
auto eventsBasedObject = eventsBasedObjectUniquePtr.get();
|
|
worker.Launch(eventsBasedObject->GetObjects());
|
|
|
|
for (auto &&variantUniquePtr :
|
|
eventsBasedObject->GetVariants().GetInternalVector()) {
|
|
auto variant = variantUniquePtr.get();
|
|
worker.Launch(variant->GetObjects());
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
void ProjectBrowserHelper::ExposeLayoutObjects(gd::Layout &layout,
|
|
gd::ArbitraryObjectsWorker &worker) {
|
|
// In the future, layouts may have children object containers.
|
|
|
|
// Layout objects
|
|
worker.Launch(layout.GetObjects());
|
|
}
|
|
|
|
void ProjectBrowserHelper::ExposeProjectFunctions(
|
|
gd::Project &project, gd::ArbitraryEventsFunctionsWorker &worker) {
|
|
|
|
for (std::size_t e = 0; e < project.GetEventsFunctionsExtensionsCount();
|
|
e++) {
|
|
auto &eventsFunctionsExtension = project.GetEventsFunctionsExtension(e);
|
|
worker.Launch(eventsFunctionsExtension.GetEventsFunctions());
|
|
|
|
for (auto &&eventsBasedBehavior :
|
|
eventsFunctionsExtension.GetEventsBasedBehaviors()
|
|
.GetInternalVector()) {
|
|
worker.Launch(eventsBasedBehavior->GetEventsFunctions());
|
|
}
|
|
|
|
for (auto &&eventsBasedObject :
|
|
eventsFunctionsExtension.GetEventsBasedObjects().GetInternalVector()) {
|
|
worker.Launch(eventsBasedObject->GetEventsFunctions());
|
|
}
|
|
}
|
|
};
|
|
|
|
void ProjectBrowserHelper::ExposeProjectEventBasedBehaviors(
|
|
gd::Project &project, gd::ArbitraryEventBasedBehaviorsWorker &worker) {
|
|
for (std::size_t e = 0; e < project.GetEventsFunctionsExtensionsCount();
|
|
e++) {
|
|
auto &eventsFunctionsExtension = project.GetEventsFunctionsExtension(e);
|
|
worker.Launch(eventsFunctionsExtension.GetEventsBasedBehaviors());
|
|
}
|
|
}
|
|
|
|
void ProjectBrowserHelper::ExposeProjectSharedDatas(
|
|
gd::Project &project, gd::ArbitraryBehaviorSharedDataWorker &worker) {
|
|
for (std::size_t i = 0; i < project.GetLayoutsCount(); ++i) {
|
|
gd::Layout &layout = project.GetLayout(i);
|
|
worker.Launch(layout.GetAllBehaviorSharedData());
|
|
}
|
|
}
|
|
|
|
} // namespace gd
|