mirror of
https://github.com/Heretek-AI/GDevelop.git
synced 2026-07-21 17:45:25 -04:00
3846a1553b
Co-authored-by: Davy Hélard <davy.helard@gmail.com> Don't show in changelog
220 lines
8.1 KiB
C++
220 lines
8.1 KiB
C++
/*
|
|
* GDevelop JS Platform
|
|
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
|
* reserved. This project is released under the MIT License.
|
|
*/
|
|
#include "GDJS/IDE/Exporter.h"
|
|
|
|
#include <algorithm>
|
|
#include <fstream>
|
|
#include <sstream>
|
|
#include <streambuf>
|
|
#include <string>
|
|
|
|
#include "GDCore/CommonTools.h"
|
|
#include "GDCore/Events/CodeGeneration/DiagnosticReport.h"
|
|
#include "GDCore/Extensions/Metadata/InGameEditorResourceMetadata.h"
|
|
#include "GDCore/IDE/AbstractFileSystem.h"
|
|
#include "GDCore/IDE/Events/UsedExtensionsFinder.h"
|
|
#include "GDCore/IDE/Project/ProjectResourcesCopier.h"
|
|
#include "GDCore/IDE/Project/SceneResourcesFinder.h"
|
|
#include "GDCore/IDE/ProjectStripper.h"
|
|
#include "GDCore/Project/EventsBasedObject.h"
|
|
#include "GDCore/Project/EventsBasedObjectVariant.h"
|
|
#include "GDCore/Project/EventsFunctionsExtension.h"
|
|
#include "GDCore/Project/ExternalEvents.h"
|
|
#include "GDCore/Project/ExternalLayout.h"
|
|
#include "GDCore/Project/Layout.h"
|
|
#include "GDCore/Project/Project.h"
|
|
#include "GDCore/Serialization/Serializer.h"
|
|
#include "GDCore/Tools/Localization.h"
|
|
#include "GDCore/Tools/Log.h"
|
|
#include "GDJS/Events/CodeGeneration/EventsCodeGenerator.h"
|
|
#include "GDJS/IDE/ExporterHelper.h"
|
|
|
|
#undef CopyFile // Disable an annoying macro
|
|
|
|
namespace gdjs {
|
|
|
|
static void InsertUnique(std::vector<gd::String> &container, gd::String str) {
|
|
if (std::find(container.begin(), container.end(), str) == container.end())
|
|
container.push_back(str);
|
|
}
|
|
|
|
Exporter::Exporter(gd::AbstractFileSystem &fileSystem, gd::String gdjsRoot_)
|
|
: fs(fileSystem), gdjsRoot(gdjsRoot_) {
|
|
SetCodeOutputDirectory(fs.GetTempDir() + "/GDTemporaries/JSCodeTemp");
|
|
}
|
|
|
|
Exporter::~Exporter() {}
|
|
|
|
bool Exporter::ExportProjectForPixiPreview(
|
|
const PreviewExportOptions &options) {
|
|
ExporterHelper helper(fs, gdjsRoot, codeOutputDir);
|
|
return helper.ExportProjectForPixiPreview(options, includesFiles);
|
|
}
|
|
|
|
bool Exporter::ExportWholePixiProject(const ExportOptions &options) {
|
|
ExporterHelper helper(fs, gdjsRoot, codeOutputDir);
|
|
gd::Project exportedProject = options.project;
|
|
|
|
auto usedExtensionsResult =
|
|
gd::UsedExtensionsFinder::ScanProject(options.project);
|
|
auto &usedExtensions = usedExtensionsResult.GetUsedExtensions();
|
|
|
|
auto exportProject = [this,
|
|
&exportedProject,
|
|
&options,
|
|
&helper,
|
|
&usedExtensionsResult](gd::String exportDir) {
|
|
gd::WholeProjectDiagnosticReport &wholeProjectDiagnosticReport =
|
|
options.project.GetWholeProjectDiagnosticReport();
|
|
wholeProjectDiagnosticReport.Clear();
|
|
|
|
// Use project properties fallback to set empty properties
|
|
if (exportedProject.GetAuthorIds().empty() &&
|
|
!options.fallbackAuthorId.empty()) {
|
|
exportedProject.GetAuthorIds().push_back(options.fallbackAuthorId);
|
|
}
|
|
if (exportedProject.GetAuthorUsernames().empty() &&
|
|
!options.fallbackAuthorUsername.empty()) {
|
|
exportedProject.GetAuthorUsernames().push_back(
|
|
options.fallbackAuthorUsername);
|
|
}
|
|
|
|
// Prepare the export directory
|
|
fs.MkDir(exportDir);
|
|
includesFiles.clear();
|
|
std::vector<gd::String> resourcesFiles;
|
|
|
|
// Export the resources (before generating events as some resources
|
|
// filenames may be updated)
|
|
helper.ExportResources(fs, exportedProject, exportDir);
|
|
|
|
// Compatibility with GD <= 5.0-beta56
|
|
// Stay compatible with text objects declaring their font as just a filename
|
|
// without a font resource - by manually adding these resources.
|
|
helper.AddDeprecatedFontFilesToFontResources(
|
|
fs, exportedProject.GetResourcesManager(), exportDir);
|
|
// end of compatibility code
|
|
|
|
// Export engine libraries
|
|
helper.AddLibsInclude(
|
|
/*pixiRenderers=*/true,
|
|
usedExtensionsResult.Has3DObjects(),
|
|
/*isInGameEditor=*/false,
|
|
/*includeWebsocketDebuggerClient=*/false,
|
|
/*includeWindowMessageDebuggerClient=*/false,
|
|
/*includeMinimalDebuggerClient=*/false,
|
|
/*includeCaptureManager*/ false,
|
|
/*includeInAppTutorialMessage*/ false,
|
|
exportedProject.GetLoadingScreen().GetGDevelopLogoStyle(),
|
|
includesFiles);
|
|
|
|
// Export files for free function, object and behaviors
|
|
for (const auto &includeFile : usedExtensionsResult.GetUsedIncludeFiles()) {
|
|
InsertUnique(includesFiles, includeFile);
|
|
}
|
|
for (const auto &requiredFile :
|
|
usedExtensionsResult.GetUsedRequiredFiles()) {
|
|
InsertUnique(resourcesFiles, requiredFile);
|
|
}
|
|
|
|
// Export effects (after engine libraries as they auto-register themselves
|
|
// to the engine)
|
|
helper.ExportEffectIncludes(exportedProject, includesFiles);
|
|
|
|
// Export events
|
|
if (!helper.ExportScenesEventsCode(exportedProject,
|
|
codeOutputDir,
|
|
includesFiles,
|
|
wholeProjectDiagnosticReport,
|
|
false)) {
|
|
gd::LogError(_("Error during exporting! Unable to export events:\n") +
|
|
lastError);
|
|
return false;
|
|
}
|
|
|
|
//...and export it
|
|
gd::SerializerElement noRuntimeGameOptions;
|
|
std::vector<gd::InGameEditorResourceMetadata> noInGameEditorResources;
|
|
helper.ExportProjectData(fs, exportedProject, codeOutputDir + "/data.js",
|
|
noRuntimeGameOptions, false, noInGameEditorResources);
|
|
includesFiles.push_back(codeOutputDir + "/data.js");
|
|
|
|
helper.ExportIncludesAndLibs(includesFiles, exportDir, false);
|
|
helper.ExportIncludesAndLibs(resourcesFiles, exportDir, false);
|
|
|
|
gd::String source = gdjsRoot + "/Runtime/index.html";
|
|
if (options.target == "cordova")
|
|
source = gdjsRoot + "/Runtime/Cordova/www/index.html";
|
|
else if (options.target == "facebookInstantGames")
|
|
source = gdjsRoot + "/Runtime/FacebookInstantGames/index.html";
|
|
|
|
if (!helper.ExportIndexFile(exportedProject,
|
|
source,
|
|
exportDir,
|
|
includesFiles,
|
|
usedExtensionsResult.GetUsedSourceFiles(),
|
|
/*nonRuntimeScriptsCacheBurst=*/0,
|
|
"")) {
|
|
gd::LogError(_("Error during export:\n") + lastError);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
};
|
|
|
|
if (options.target == "cordova") {
|
|
fs.MkDir(options.exportPath);
|
|
fs.MkDir(options.exportPath + "/www");
|
|
|
|
if (!exportProject(options.exportPath + "/www")) return false;
|
|
|
|
if (!helper.ExportCordovaFiles(
|
|
exportedProject, options.exportPath, usedExtensions))
|
|
return false;
|
|
} else if (options.target == "electron") {
|
|
fs.MkDir(options.exportPath);
|
|
|
|
if (!exportProject(options.exportPath + "/app")) return false;
|
|
|
|
if (!helper.ExportElectronFiles(
|
|
exportedProject, options.exportPath, usedExtensions))
|
|
return false;
|
|
|
|
if (!helper.ExportBuildResourcesElectronFiles(exportedProject,
|
|
options.exportPath))
|
|
return false;
|
|
} else if (options.target == "facebookInstantGames") {
|
|
if (!exportProject(options.exportPath)) return false;
|
|
|
|
if (!helper.ExportFacebookInstantGamesFiles(exportedProject,
|
|
options.exportPath))
|
|
return false;
|
|
} else {
|
|
if (!exportProject(options.exportPath)) return false;
|
|
|
|
if (!helper.ExportHtml5Files(exportedProject, options.exportPath))
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void Exporter::SerializeProjectData(const gd::Project &project,
|
|
const PreviewExportOptions &options,
|
|
gd::SerializerElement &projectDataElement) {
|
|
std::vector<gd::InGameEditorResourceMetadata> noInGameEditorResources;
|
|
ExporterHelper::SerializeProjectData(fs, project, options, projectDataElement, noInGameEditorResources);
|
|
}
|
|
|
|
void Exporter::SerializeRuntimeGameOptions(
|
|
const PreviewExportOptions &options,
|
|
gd::SerializerElement &runtimeGameOptionsElement) {
|
|
ExporterHelper::SerializeRuntimeGameOptions(
|
|
fs, gdjsRoot, options, includesFiles, runtimeGameOptionsElement);
|
|
}
|
|
|
|
} // namespace gdjs
|