Files
GDevelop/Core/GDCore/IDE/ExportedDependencyResolver.h
2024-10-14 12:06:42 +02:00

128 lines
4.9 KiB
C++

#pragma once
#include <vector>
#include "GDCore/Extensions/Metadata/DependencyMetadata.h"
#include "GDCore/Extensions/PlatformExtension.h"
#include "GDCore/Project/Project.h"
#include "GDCore/Extensions/Platform.h"
namespace gd {
/**
* \brief Store references to a gd::DependencyMetadata and its associated
* gd::PlatformExtension.
*
* \note Both objects must be kept alive, as this is keeping a pointer to them.
*/
struct DependencyMetadataAndExtension {
DependencyMetadataAndExtension(gd::DependencyMetadata &dependency_,
gd::PlatformExtension &extension_)
: dependency(&dependency_), extension(&extension_){};
gd::DependencyMetadata &GetDependency() const { return *dependency; };
gd::PlatformExtension &GetExtension() const { return *extension; };
private:
gd::DependencyMetadata *dependency;
gd::PlatformExtension *extension;
};
/**
* \brief Helpers to manipulate dependencies of extensions to be exported along
* with a game.
*/
class ExportedDependencyResolver {
public:
/**
* \brief Return the list of dependencies to be exported for the given
* project, used extensions list and dependency type.
*
* Not all dependencies declared by extensions must be exported: some are only
* exported when some settings are filled. Then, some others are only exported
* when some other dependencies are exported (this won't work for more than
* one level though).
*/
static std::vector<DependencyMetadataAndExtension> GetDependenciesFor(
const gd::Project &project,
std::set<gd::String> usedExtensions,
const gd::String &dependencyType) {
std::vector<DependencyMetadataAndExtension> dependenciesWithProperType;
for (const gd::String &extensionName : usedExtensions) {
auto extension = project.GetCurrentPlatform().GetExtension(extensionName);
for (gd::DependencyMetadata &dependency :
extension->GetAllDependencies()) {
if (dependency.GetDependencyType() == dependencyType) {
DependencyMetadataAndExtension dependencyMetadataAndExtension(
dependency, *extension);
dependenciesWithProperType.push_back(dependencyMetadataAndExtension);
}
}
}
// Keep only the dependencies that have their extra settings filled
// and those that don't require extra settings to be filled.
std::vector<DependencyMetadataAndExtension> dependenciesWithFilledSettings;
for (auto dependencyAndExtension : dependenciesWithProperType) {
auto &dependency = dependencyAndExtension.GetDependency();
auto extraSettingValues = GetExtensionDependencyExtraSettingValues(
project, dependencyAndExtension);
bool hasExtraSettings = !extraSettingValues.empty();
if (!dependency.IsOnlyIfSomeExtraSettingsNonEmpty() || hasExtraSettings)
dependenciesWithFilledSettings.push_back(dependencyAndExtension);
}
// Keep only the dependency that depends on another dependencies that is
// exported (or dependencies that don't require another dependency).
std::vector<DependencyMetadataAndExtension> exportedDependencies;
for (auto dependencyAndExtension : dependenciesWithFilledSettings) {
auto &dependency = dependencyAndExtension.GetDependency();
auto &otherDependencyName =
dependency.GetOtherDependencyThatMustBeExported();
if (otherDependencyName.empty() ||
std::find_if(
dependenciesWithFilledSettings.begin(),
dependenciesWithFilledSettings.end(),
[&otherDependencyName](
DependencyMetadataAndExtension &otherDependencyAndExtension) {
return otherDependencyAndExtension.GetDependency().GetName() ==
otherDependencyName;
}) != dependenciesWithFilledSettings.end()) {
exportedDependencies.push_back(dependencyAndExtension);
}
}
return exportedDependencies;
}
/**
* \brief Return the values that were stored in the project for the given
* dependency.
*/
static std::map<gd::String, gd::String>
GetExtensionDependencyExtraSettingValues(
const gd::Project &project,
const gd::DependencyMetadataAndExtension &dependencyAndExtension) {
std::map<gd::String, gd::String> values;
auto &dependency = dependencyAndExtension.GetDependency();
const gd::String &extensionName =
dependencyAndExtension.GetExtension().GetName();
for (const auto &extraSetting : dependency.GetAllExtraSettings()) {
const gd::String &type = extraSetting.second.GetType();
const gd::String extraSettingValue =
type == "ExtensionProperty"
? project.GetExtensionProperties().GetValue(
extensionName, extraSetting.second.GetValue())
: extraSetting.second.GetValue();
if (!extraSettingValue.empty())
values[extraSetting.first] = extraSettingValue;
}
return values;
};
};
} // namespace gd