mirror of
https://github.com/4ian/GDevelop.git
synced 2025-10-15 10:19:04 +00:00
Merge pull request #443 from 4ian/feature/cordova-icons
Add support for icons when exporting to Android/iOS
This commit is contained in:
@@ -45,7 +45,7 @@ bool ProjectResourcesCopier::CopyAllResourcesTo(gd::Project & originalProject, A
|
||||
#endif
|
||||
|
||||
auto projectDirectory = fs.DirNameFrom(originalProject.GetProjectFile());
|
||||
std::cout << "Copying all ressources from " << projectDirectory << " to " << destinationDirectory;
|
||||
std::cout << "Copying all ressources from " << projectDirectory << " to " << destinationDirectory << "..." << std::endl;
|
||||
|
||||
//Get the resources to be copied
|
||||
gd::ResourcesMergingHelper resourcesMergingHelper(fs);
|
||||
|
58
Core/GDCore/Project/PlatformSpecificAssets.cpp
Normal file
58
Core/GDCore/Project/PlatformSpecificAssets.cpp
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2018 Florian Rival (Florian.Rival@gmail.com). All rights reserved.
|
||||
* This project is released under the MIT License.
|
||||
*/
|
||||
|
||||
#include "PlatformSpecificAssets.h"
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
#include "GDCore/IDE/Project/ArbitraryResourceWorker.h"
|
||||
|
||||
namespace gd {
|
||||
|
||||
gd::String PlatformSpecificAssets::badStr;
|
||||
|
||||
bool PlatformSpecificAssets::Has(const gd::String& platform, const gd::String& name) const
|
||||
{
|
||||
return assets.find(platform + "-" + name) != assets.end();
|
||||
}
|
||||
|
||||
const gd::String& PlatformSpecificAssets::Get(const gd::String& platform, const gd::String& name) const
|
||||
{
|
||||
const auto & it = assets.find(platform + "-" + name);
|
||||
return it != assets.end() ? it->second : badStr;
|
||||
}
|
||||
|
||||
void PlatformSpecificAssets::Remove(const gd::String& platform, const gd::String& name)
|
||||
{
|
||||
assets.erase(platform + "-" + name);
|
||||
}
|
||||
|
||||
void PlatformSpecificAssets::Set(const gd::String& platform, const gd::String& name, const gd::String& resourceName)
|
||||
{
|
||||
assets[platform + "-" + name] = resourceName;
|
||||
}
|
||||
|
||||
void PlatformSpecificAssets::SerializeTo(SerializerElement& element) const
|
||||
{
|
||||
for (auto& it : assets) {
|
||||
element.AddChild(it.first).SetValue(it.second);
|
||||
}
|
||||
}
|
||||
|
||||
void PlatformSpecificAssets::UnserializeFrom(const SerializerElement& element)
|
||||
{
|
||||
assets.clear();
|
||||
|
||||
for (auto& child : element.GetAllChildren()) {
|
||||
assets[child.first] = child.second->GetValue().GetString();
|
||||
}
|
||||
}
|
||||
|
||||
void PlatformSpecificAssets::ExposeResources(gd::ArbitraryResourceWorker & worker)
|
||||
{
|
||||
for (auto& it : assets) {
|
||||
worker.ExposeImage(it.second);
|
||||
}
|
||||
}
|
||||
}
|
76
Core/GDCore/Project/PlatformSpecificAssets.h
Normal file
76
Core/GDCore/Project/PlatformSpecificAssets.h
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2018 Florian Rival (Florian.Rival@gmail.com). All rights reserved.
|
||||
* This project is released under the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef GDCORE_PLATFORMASSETS_H
|
||||
#define GDCORE_PLATFORMASSETS_H
|
||||
#include "GDCore/String.h"
|
||||
#include <map>
|
||||
namespace gd {
|
||||
class SerializerElement;
|
||||
}
|
||||
namespace gd {
|
||||
class ArbitraryResourceWorker;
|
||||
}
|
||||
|
||||
namespace gd {
|
||||
|
||||
/**
|
||||
* \brief Store the icons, splashscreens or reference to any other asset
|
||||
* that can be needed when exporting the game.
|
||||
*
|
||||
* \see gd::Project
|
||||
*
|
||||
* \ingroup PlatformDefinition
|
||||
*/
|
||||
class GD_CORE_API PlatformSpecificAssets {
|
||||
public:
|
||||
PlatformSpecificAssets(){};
|
||||
virtual ~PlatformSpecificAssets(){};
|
||||
|
||||
/**
|
||||
* \brief Return true if the specified asset exists.
|
||||
*/
|
||||
bool Has(const gd::String& platform, const gd::String& name) const;
|
||||
|
||||
/**
|
||||
* \brief Get the specified asset resource name.
|
||||
*/
|
||||
const gd::String& Get(const gd::String& platform, const gd::String& name) const;
|
||||
|
||||
/**
|
||||
* \brief Remove the specified asset.
|
||||
*/
|
||||
void Remove(const gd::String& platform, const gd::String& name);
|
||||
|
||||
/**
|
||||
* \brief Remove the specified asset.
|
||||
*/
|
||||
void Set(const gd::String& platform, const gd::String& name, const gd::String& resourceName);
|
||||
|
||||
void ExposeResources(gd::ArbitraryResourceWorker & worker);
|
||||
|
||||
/** \name Saving and loading
|
||||
*/
|
||||
///@{
|
||||
/**
|
||||
* \brief Serialize objects groups container.
|
||||
*/
|
||||
void SerializeTo(SerializerElement& element) const;
|
||||
|
||||
/**
|
||||
* \brief Unserialize the objects groups container.
|
||||
*/
|
||||
void UnserializeFrom(const SerializerElement& element);
|
||||
///@}
|
||||
|
||||
private:
|
||||
std::map<gd::String, gd::String> assets;
|
||||
|
||||
static gd::String badStr;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // GDCORE_PLATFORMASSETS_H
|
@@ -61,6 +61,7 @@ Project::Project() :
|
||||
#if defined(GD_IDE_ONLY)
|
||||
name(_("Project")),
|
||||
packageName("com.example.gamename"),
|
||||
orientation("landscape"),
|
||||
folderProject(false),
|
||||
#endif
|
||||
windowWidth(800),
|
||||
@@ -531,9 +532,11 @@ void Project::UnserializeFrom(const SerializerElement & element)
|
||||
#if defined(GD_IDE_ONLY)
|
||||
SetAuthor(propElement.GetChild("author", 0, "Auteur").GetValue().GetString());
|
||||
SetPackageName(propElement.GetStringAttribute("packageName"));
|
||||
SetOrientation(propElement.GetStringAttribute("orientation", "default"));
|
||||
SetFolderProject(propElement.GetBoolAttribute("folderProject"));
|
||||
SetProjectFile(propElement.GetStringAttribute("projectFile"));
|
||||
SetLastCompilationDirectory(propElement.GetChild("latestCompilationDirectory", 0, "LatestCompilationDirectory").GetValue().GetString());
|
||||
platformSpecificAssets.UnserializeFrom(propElement.GetChild("platformSpecificAssets"));
|
||||
winExecutableFilename = propElement.GetStringAttribute("winExecutableFilename");
|
||||
winExecutableIconFile = propElement.GetStringAttribute("winExecutableIconFile");
|
||||
linuxExecutableFilename = propElement.GetStringAttribute("linuxExecutableFilename");
|
||||
@@ -743,6 +746,8 @@ void Project::SerializeTo(SerializerElement & element) const
|
||||
propElement.SetAttribute("projectFile", gameFile);
|
||||
propElement.SetAttribute("folderProject", folderProject);
|
||||
propElement.SetAttribute("packageName", packageName);
|
||||
propElement.SetAttribute("orientation", orientation);
|
||||
platformSpecificAssets.SerializeTo(propElement.AddChild("platformSpecificAssets"));
|
||||
propElement.SetAttribute("winExecutableFilename", winExecutableFilename);
|
||||
propElement.SetAttribute("winExecutableIconFile", winExecutableIconFile);
|
||||
propElement.SetAttribute("linuxExecutableFilename", linuxExecutableFilename);
|
||||
@@ -815,6 +820,7 @@ void Project::ExposeResources(gd::ArbitraryResourceWorker & worker)
|
||||
{
|
||||
//Add project resources
|
||||
worker.ExposeResources(&GetResourcesManager());
|
||||
platformSpecificAssets.ExposeResources(worker);
|
||||
#if !defined(GD_NO_WX_GUI)
|
||||
gd::SafeYield::Do();
|
||||
#endif
|
||||
@@ -1019,8 +1025,10 @@ void Project::Init(const gd::Project & game)
|
||||
#if defined(GD_IDE_ONLY)
|
||||
author = game.author;
|
||||
packageName = game.packageName;
|
||||
orientation = game.orientation;
|
||||
folderProject = game.folderProject;
|
||||
latestCompilationDirectory = game.latestCompilationDirectory;
|
||||
platformSpecificAssets = game.platformSpecificAssets;
|
||||
objectGroups = game.objectGroups;
|
||||
|
||||
GDMajorVersion = game.GDMajorVersion;
|
||||
|
@@ -16,6 +16,7 @@ class TiXmlElement;
|
||||
#include "GDCore/Project/ChangesNotifier.h"
|
||||
#include "GDCore/Project/VariablesContainer.h"
|
||||
#include "GDCore/Project/ResourcesManager.h"
|
||||
#include "GDCore/Project/PlatformSpecificAssets.h"
|
||||
#include "GDCore/Project/ObjectGroupsContainer.h"
|
||||
namespace gd { class Platform; }
|
||||
namespace gd { class Layout; }
|
||||
@@ -85,6 +86,18 @@ public:
|
||||
*/
|
||||
const gd::String & GetPackageName() const { return packageName; }
|
||||
|
||||
/**
|
||||
* \brief Change the project orientation (in particular when exported with Cordova).
|
||||
* This has no effect on desktop and web browsers.
|
||||
* \param orientation The orientation to use ("default", "landscape", "portrait").
|
||||
*/
|
||||
void SetOrientation(const gd::String & orientation_) { orientation = orientation_; };
|
||||
|
||||
/**
|
||||
* \brief Get project orientation ("default", "landscape", "portrait").
|
||||
*/
|
||||
const gd::String & GetOrientation() const { return orientation; }
|
||||
|
||||
/**
|
||||
* Called when project file has changed.
|
||||
*/
|
||||
@@ -118,6 +131,16 @@ public:
|
||||
* \see gd::Project::SetLastCompilationDirectory
|
||||
*/
|
||||
const gd::String & GetLastCompilationDirectory() const {return latestCompilationDirectory;}
|
||||
|
||||
/**
|
||||
* \brief Return a reference to platform assets of the project (icons, splashscreen...).
|
||||
*/
|
||||
gd::PlatformSpecificAssets & GetPlatformSpecificAssets() { return platformSpecificAssets; }
|
||||
|
||||
/**
|
||||
* \brief Return a reference to platform assets of the project (icons, splashscreen...).
|
||||
*/
|
||||
const gd::PlatformSpecificAssets & GetPlatformSpecificAssets() const { return platformSpecificAssets; }
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -737,10 +760,12 @@ private:
|
||||
gd::ObjectGroupsContainer objectGroups; ///< Global objects groups
|
||||
gd::String author; ///< Game author name
|
||||
gd::String packageName; ///< Game package name
|
||||
gd::String orientation; ///< Lock game orientation (on mobile devices). "default", "landscape" or "portrait".
|
||||
bool folderProject; ///< True if folder project, false if single file project.
|
||||
gd::String gameFile; ///< File of the game
|
||||
gd::String latestCompilationDirectory; ///< File of the game
|
||||
gd::Platform* currentPlatform; ///< The platform being used to edit the project.
|
||||
gd::PlatformSpecificAssets platformSpecificAssets;
|
||||
std::vector < std::unique_ptr<gd::ExternalEvents> > externalEvents; ///< List of all externals events
|
||||
mutable unsigned int GDMajorVersion; ///< The GD major version used the last time the project was saved.
|
||||
mutable unsigned int GDMinorVersion; ///< The GD minor version used the last time the project was saved.
|
||||
|
@@ -97,8 +97,9 @@ bool Exporter::ExportWholePixiProject(gd::Project & project, gd::String exportDi
|
||||
bool minify, bool exportForCordova)
|
||||
{
|
||||
ExporterHelper helper(fs, gdjsRoot, codeOutputDir);
|
||||
gd::Project exportedProject = project;
|
||||
|
||||
auto exportProject = [this, &project, &minify,
|
||||
auto exportProject = [this, &exportedProject, &minify,
|
||||
&exportForCordova, &helper](gd::String exportDir)
|
||||
{
|
||||
wxProgressDialog * progressDialogPtr = NULL;
|
||||
@@ -111,8 +112,6 @@ bool Exporter::ExportWholePixiProject(gd::Project & project, gd::String exportDi
|
||||
fs.MkDir(exportDir);
|
||||
std::vector<gd::String> includesFiles;
|
||||
|
||||
gd::Project exportedProject = project;
|
||||
|
||||
//Export the resources (before generating events as some resources filenames may be updated)
|
||||
helper.ExportResources(fs, exportedProject, exportDir, progressDialogPtr);
|
||||
|
||||
@@ -168,11 +167,12 @@ bool Exporter::ExportWholePixiProject(gd::Project & project, gd::String exportDi
|
||||
{
|
||||
//Prepare the export directory
|
||||
fs.MkDir(exportDir);
|
||||
if (!helper.ExportCordovaConfigFile(project, exportDir))
|
||||
return false;
|
||||
|
||||
if (!exportProject(exportDir + "/www"))
|
||||
return false;
|
||||
|
||||
if (!helper.ExportCordovaConfigFile(exportedProject, exportDir))
|
||||
return false;
|
||||
} else {
|
||||
if (!exportProject(exportDir))
|
||||
return false;
|
||||
|
@@ -156,10 +156,42 @@ bool ExporterHelper::ExportPixiIndexFile(gd::String source, gd::String exportDir
|
||||
|
||||
bool ExporterHelper::ExportCordovaConfigFile(const gd::Project & project, gd::String exportDir)
|
||||
{
|
||||
auto & platformSpecificAssets = project.GetPlatformSpecificAssets();
|
||||
auto & resourceManager = project.GetResourcesManager();
|
||||
auto getIconFilename = [&resourceManager, &platformSpecificAssets](const gd::String & platform, const gd::String & name) {
|
||||
const gd::String & file = resourceManager.GetResource(platformSpecificAssets.Get(platform, name)).GetFile();
|
||||
return file.empty() ? "" : "www/" + file;
|
||||
};
|
||||
|
||||
gd::String str = fs.ReadFile(gdjsRoot + "/Runtime/Cordova/config.xml")
|
||||
.FindAndReplace("GDJS_PROJECTNAME", project.GetName())
|
||||
.FindAndReplace("GDJS_PACKAGENAME", project.GetPackageName())
|
||||
.FindAndReplace("GDJS_ORIENTATION", "default");
|
||||
.FindAndReplace("GDJS_ORIENTATION", project.GetOrientation())
|
||||
// Android icons
|
||||
.FindAndReplace("GDJS_ICON_ANDROID_36", getIconFilename("android", "icon-36"))
|
||||
.FindAndReplace("GDJS_ICON_ANDROID_48", getIconFilename("android", "icon-48"))
|
||||
.FindAndReplace("GDJS_ICON_ANDROID_72", getIconFilename("android", "icon-72"))
|
||||
.FindAndReplace("GDJS_ICON_ANDROID_96", getIconFilename("android", "icon-96"))
|
||||
.FindAndReplace("GDJS_ICON_ANDROID_144", getIconFilename("android", "icon-144"))
|
||||
.FindAndReplace("GDJS_ICON_ANDROID_192", getIconFilename("android", "icon-192"))
|
||||
// iOS icons
|
||||
.FindAndReplace("GDJS_ICON_IOS_180", getIconFilename("ios", "icon-180"))
|
||||
.FindAndReplace("GDJS_ICON_IOS_60", getIconFilename("ios", "icon-60"))
|
||||
.FindAndReplace("GDJS_ICON_IOS_120", getIconFilename("ios", "icon-120"))
|
||||
.FindAndReplace("GDJS_ICON_IOS_76", getIconFilename("ios", "icon-76"))
|
||||
.FindAndReplace("GDJS_ICON_IOS_152", getIconFilename("ios", "icon-152"))
|
||||
.FindAndReplace("GDJS_ICON_IOS_40", getIconFilename("ios", "icon-40"))
|
||||
.FindAndReplace("GDJS_ICON_IOS_80", getIconFilename("ios", "icon-80"))
|
||||
.FindAndReplace("GDJS_ICON_IOS_57", getIconFilename("ios", "icon-57"))
|
||||
.FindAndReplace("GDJS_ICON_IOS_114", getIconFilename("ios", "icon-114"))
|
||||
.FindAndReplace("GDJS_ICON_IOS_72", getIconFilename("ios", "icon-72"))
|
||||
.FindAndReplace("GDJS_ICON_IOS_144", getIconFilename("ios", "icon-144"))
|
||||
.FindAndReplace("GDJS_ICON_IOS_167", getIconFilename("ios", "icon-167"))
|
||||
.FindAndReplace("GDJS_ICON_IOS_29", getIconFilename("ios", "icon-29"))
|
||||
.FindAndReplace("GDJS_ICON_IOS_58", getIconFilename("ios", "icon-58"))
|
||||
.FindAndReplace("GDJS_ICON_IOS_50", getIconFilename("ios", "icon-50"))
|
||||
.FindAndReplace("GDJS_ICON_IOS_100", getIconFilename("ios", "icon-100"))
|
||||
;
|
||||
|
||||
if (!fs.WriteToFile(exportDir + "/config.xml", str))
|
||||
{
|
||||
@@ -196,14 +228,14 @@ bool ExporterHelper::ExportCocos2dFiles(const gd::Project & project, gd::String
|
||||
std::vector<gd::String> noIncludesInThisFile;
|
||||
if (!CompleteIndexFile(str, customCss, customHtml, exportDir, noIncludesInThisFile, ""))
|
||||
{
|
||||
lastError = "Unable to complete Cocos2d index.html file.";
|
||||
lastError = "Unable to complete Cocos2d-JS index.html file.";
|
||||
return false;
|
||||
}
|
||||
|
||||
//Write the index.html file
|
||||
if (!fs.WriteToFile(exportDir + "/index.html", str))
|
||||
{
|
||||
lastError = "Unable to write Cocos2d index.html file.";
|
||||
lastError = "Unable to write Cocos2d-JS index.html file.";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -229,7 +261,7 @@ bool ExporterHelper::ExportCocos2dFiles(const gd::Project & project, gd::String
|
||||
|
||||
if (!fs.WriteToFile(exportDir + "/project.json", str))
|
||||
{
|
||||
lastError = "Unable to write Cocos2d project.json file.";
|
||||
lastError = "Unable to write Cocos2d-JS project.json file.";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@@ -12,10 +12,46 @@
|
||||
<allow-intent href="geo:*" />
|
||||
<platform name="android">
|
||||
<allow-intent href="market:*" />
|
||||
<icon src="GDJS_ICON_ANDROID_36" density="ldpi" />
|
||||
<icon src="GDJS_ICON_ANDROID_48" density="mdpi" />
|
||||
<icon src="GDJS_ICON_ANDROID_72" density="hdpi" />
|
||||
<icon src="GDJS_ICON_ANDROID_96" density="xhdpi" />
|
||||
<icon src="GDJS_ICON_ANDROID_144" density="xxhdpi" />
|
||||
<icon src="GDJS_ICON_ANDROID_192" density="xxxhdpi" />
|
||||
</platform>
|
||||
<platform name="ios">
|
||||
<allow-intent href="itms:*" />
|
||||
<allow-intent href="itms-apps:*" />
|
||||
<!-- iOS 8.0+ -->
|
||||
<!-- iPhone 6 Plus -->
|
||||
<icon src="GDJS_ICON_IOS_180" width="180" height="180" />
|
||||
<!-- iOS 7.0+ -->
|
||||
<!-- iPhone / iPod Touch -->
|
||||
<icon src="GDJS_ICON_IOS_60" width="60" height="60" />
|
||||
<icon src="GDJS_ICON_IOS_120" width="120" height="120" />
|
||||
<!-- iPad -->
|
||||
<icon src="GDJS_ICON_IOS_76" width="76" height="76" />
|
||||
<icon src="GDJS_ICON_IOS_152" width="152" height="152" />
|
||||
<!-- Spotlight Icon -->
|
||||
<icon src="GDJS_ICON_IOS_40" width="40" height="40" />
|
||||
<icon src="GDJS_ICON_IOS_80" width="80" height="80" />
|
||||
<!-- iOS 6.1 -->
|
||||
<!-- iPhone / iPod Touch -->
|
||||
<icon src="GDJS_ICON_IOS_57" width="57" height="57" />
|
||||
<icon src="GDJS_ICON_IOS_114" width="114" height="114" />
|
||||
<!-- iPad -->
|
||||
<icon src="GDJS_ICON_IOS_72" width="72" height="72" />
|
||||
<icon src="GDJS_ICON_IOS_144" width="144" height="144" />
|
||||
<!-- iPad Pro -->
|
||||
<icon src="GDJS_ICON_IOS_167" width="167" height="167" />
|
||||
<!-- iPhone Spotlight and Settings Icon -->
|
||||
<icon src="GDJS_ICON_IOS_29" width="29" height="29" />
|
||||
<icon src="GDJS_ICON_IOS_58" width="58" height="58" />
|
||||
<!-- iPad Spotlight and Settings Icon -->
|
||||
<icon src="GDJS_ICON_IOS_50" width="50" height="50" />
|
||||
<icon src="GDJS_ICON_IOS_100" width="100" height="100" />
|
||||
<!-- iPad Pro -->
|
||||
<icon src="GDJS_ICON_IOS_167" width="167" height="167" />
|
||||
</platform>
|
||||
<preference name="orientation" value="GDJS_ORIENTATION" />
|
||||
</widget>
|
||||
|
@@ -16,6 +16,7 @@ import PreferencesDialog from './Preferences/PreferencesDialog';
|
||||
import ConfirmCloseDialog from './ConfirmCloseDialog';
|
||||
import AboutDialog, { type UpdateStatus } from './AboutDialog';
|
||||
import ProjectManager from '../ProjectManager';
|
||||
import PlatformSpecificAssetsDialog from '../PlatformSpecificAssetsEditor/PlatformSpecificAssetsDialog';
|
||||
import LoaderModal from '../UI/LoaderModal';
|
||||
import EditorBar from '../UI/EditorBar';
|
||||
import ProfileDialog from '../Profile/ProfileDialog';
|
||||
@@ -56,6 +57,7 @@ import {
|
||||
} from './Preferences/PreferencesHandler';
|
||||
import ErrorBoundary from '../UI/ErrorBoundary';
|
||||
import SubscriptionDialog from '../Profile/SubscriptionDialog';
|
||||
import ResourcesLoader from '../ResourcesLoader/index';
|
||||
|
||||
const gd = global.gd;
|
||||
|
||||
@@ -88,6 +90,7 @@ type State = {|
|
||||
updateStatus: UpdateStatus,
|
||||
aboutDialogOpen: boolean,
|
||||
onSubscriptionDialogClosed: ?Function,
|
||||
platformSpecificAssetsDialogOpen: boolean,
|
||||
|};
|
||||
|
||||
export default class MainFrame extends Component<*, State> {
|
||||
@@ -112,6 +115,7 @@ export default class MainFrame extends Component<*, State> {
|
||||
updateStatus: { message: '', status: 'unknown' },
|
||||
aboutDialogOpen: false,
|
||||
onSubscriptionDialogClosed: null,
|
||||
platformSpecificAssetsDialogOpen: false,
|
||||
};
|
||||
toolbar = null;
|
||||
confirmCloseDialog: any = null;
|
||||
@@ -140,6 +144,11 @@ export default class MainFrame extends Component<*, State> {
|
||||
|
||||
loadFromProject = (project: gdProject, cb: Function) => {
|
||||
this.closeProject(() => {
|
||||
// Make sure that the ResourcesLoader cache is emptied, so that
|
||||
// the URL to a resource with a name in the old project is not re-used
|
||||
// for another resource with the same name in the new project.
|
||||
ResourcesLoader.burstUrlsCache();
|
||||
|
||||
this.setState(
|
||||
{
|
||||
currentProject: project,
|
||||
@@ -759,6 +768,12 @@ export default class MainFrame extends Component<*, State> {
|
||||
});
|
||||
};
|
||||
|
||||
openPlatformSpecificAssets = (open: boolean = true) => {
|
||||
this.setState({
|
||||
platformSpecificAssetsDialogOpen: open,
|
||||
});
|
||||
};
|
||||
|
||||
setUpdateStatus = (status: UpdateStatus) => {
|
||||
this.setState({
|
||||
updateStatus: status,
|
||||
@@ -846,6 +861,8 @@ export default class MainFrame extends Component<*, State> {
|
||||
onExportProject={this.openExportDialog}
|
||||
onOpenPreferences={() => this.openPreferences(true)}
|
||||
onOpenResources={() => this.openResources()}
|
||||
onOpenPlatformSpecificAssets={() =>
|
||||
this.openPlatformSpecificAssets()}
|
||||
/>
|
||||
)}
|
||||
</Drawer>
|
||||
@@ -928,6 +945,16 @@ export default class MainFrame extends Component<*, State> {
|
||||
open: this.state.saveDialogOpen,
|
||||
onClose: () => this._openSaveDialog(false),
|
||||
})}
|
||||
{!!this.state.currentProject && (
|
||||
<PlatformSpecificAssetsDialog
|
||||
project={this.state.currentProject}
|
||||
open={this.state.platformSpecificAssetsDialogOpen}
|
||||
onApply={() => this.openPlatformSpecificAssets(false)}
|
||||
onClose={() => this.openPlatformSpecificAssets(false)}
|
||||
resourceSources={resourceSources}
|
||||
onChooseResource={this._onChooseResource}
|
||||
/>
|
||||
)}
|
||||
{!!genericDialog &&
|
||||
React.cloneElement(genericDialog, {
|
||||
open: this.state.genericDialogOpen,
|
||||
|
@@ -2,7 +2,7 @@ import React, { Component } from 'react';
|
||||
import TextField from 'material-ui/TextField';
|
||||
import Checkbox from 'material-ui/Checkbox';
|
||||
import { Line, Column } from '../../UI/Grid';
|
||||
import ResourcesLoader from '../../ObjectsRendering/ResourcesLoader';
|
||||
import ResourcesLoader from '../../ResourcesLoader';
|
||||
import ResourceSelectorWithThumbnail from '../ResourceSelectorWithThumbnail';
|
||||
const gd = global.gd;
|
||||
|
||||
|
@@ -15,7 +15,7 @@ import MiniToolbar from '../../../UI/MiniToolbar';
|
||||
import DragHandle from '../../../UI/DragHandle';
|
||||
import ContextMenu from '../../../UI/Menu/ContextMenu';
|
||||
import { showWarningBox } from '../../../UI/Messages/MessageBox';
|
||||
import ResourcesLoader from '../../../ObjectsRendering/ResourcesLoader';
|
||||
import ResourcesLoader from '../../../ResourcesLoader';
|
||||
import PointsEditor from './PointsEditor';
|
||||
import { deleteSpritesFromAnimation } from './Utils/SpriteObjectHelper';
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import React, { Component } from 'react';
|
||||
import TextField from 'material-ui/TextField';
|
||||
import { Line, Column } from '../../UI/Grid';
|
||||
import ResourcesLoader from '../../ObjectsRendering/ResourcesLoader';
|
||||
import ResourcesLoader from '../../ResourcesLoader';
|
||||
import ResourceSelectorWithThumbnail from '../ResourceSelectorWithThumbnail';
|
||||
const gd = global.gd;
|
||||
|
||||
|
@@ -1,4 +1,6 @@
|
||||
import React from 'react';
|
||||
// @flow
|
||||
import * as React from 'react';
|
||||
import ResourcesLoader from '../ResourcesLoader';
|
||||
|
||||
const MARGIN = 50;
|
||||
|
||||
@@ -29,12 +31,50 @@ const styles = {
|
||||
},
|
||||
};
|
||||
|
||||
export default class ImagePreview extends React.Component {
|
||||
state = {
|
||||
errored: false,
|
||||
imageWidth: null,
|
||||
imageHeight: null,
|
||||
};
|
||||
type Props = {|
|
||||
project: gdProject,
|
||||
resourceName: string,
|
||||
resourcesLoader: typeof ResourcesLoader,
|
||||
children?: any,
|
||||
style?: Object,
|
||||
|};
|
||||
|
||||
type State = {|
|
||||
errored: boolean,
|
||||
imageWidth: ?number,
|
||||
imageHeight: ?number,
|
||||
imageSource: ?string,
|
||||
|};
|
||||
|
||||
export default class ImagePreview extends React.Component<Props, State> {
|
||||
_container: ?HTMLDivElement = null;
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
this.state = this._loadFrom(props);
|
||||
}
|
||||
|
||||
componentWillReceiveProps(newProps: Props) {
|
||||
if (
|
||||
newProps.resourceName !== this.props.resourceName ||
|
||||
newProps.project !== this.props.project ||
|
||||
newProps.resourcesLoader !== this.props.resourcesLoader
|
||||
) {
|
||||
this.setState(this._loadFrom(newProps));
|
||||
}
|
||||
}
|
||||
|
||||
_loadFrom(props: Props): State {
|
||||
const { project, resourceName, resourcesLoader } = props;
|
||||
return {
|
||||
errored: false,
|
||||
imageWidth: null,
|
||||
imageHeight: null,
|
||||
imageSource:
|
||||
resourcesLoader.getResourceFullUrl(project, resourceName),
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (this._container) {
|
||||
@@ -49,7 +89,7 @@ export default class ImagePreview extends React.Component {
|
||||
});
|
||||
};
|
||||
|
||||
_handleImageLoaded = (e, t) => {
|
||||
_handleImageLoaded = (e: any) => {
|
||||
const imgElement = e.target;
|
||||
|
||||
this.setState({
|
||||
@@ -59,15 +99,9 @@ export default class ImagePreview extends React.Component {
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
project,
|
||||
resourceName,
|
||||
resourcesLoader,
|
||||
style,
|
||||
children,
|
||||
} = this.props;
|
||||
const { resourceName, style, children } = this.props;
|
||||
|
||||
const { imageHeight, imageWidth } = this.state;
|
||||
const { imageHeight, imageWidth, imageSource } = this.state;
|
||||
|
||||
const overlayStyle = {
|
||||
...styles.overlayContainer,
|
||||
@@ -86,9 +120,10 @@ export default class ImagePreview extends React.Component {
|
||||
<img
|
||||
style={styles.spriteThumbnailImage}
|
||||
alt={resourceName}
|
||||
src={resourcesLoader.getResourceFullFilename(project, resourceName)}
|
||||
src={imageSource}
|
||||
onError={this._handleError}
|
||||
onLoad={this._handleImageLoaded}
|
||||
crossOrigin="anonymous"
|
||||
/>
|
||||
)}
|
||||
{canDisplayOverlays &&
|
||||
|
@@ -58,13 +58,14 @@ const ThemableImageThumbnail = ({
|
||||
}}
|
||||
onContextMenu={e => {
|
||||
e.stopPropagation();
|
||||
onContextMenu(e.clientX, e.clientY);
|
||||
if (onContextMenu) onContextMenu(e.clientX, e.clientY);
|
||||
}}
|
||||
>
|
||||
<img
|
||||
style={styles.spriteThumbnailImage}
|
||||
alt={resourceName}
|
||||
src={resourcesLoader.getResourceFullFilename(project, resourceName)}
|
||||
src={resourcesLoader.getResourceFullUrl(project, resourceName)}
|
||||
crossOrigin="anonymous"
|
||||
/>
|
||||
{selectable && (
|
||||
<div style={styles.checkboxContainer}>
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import ResourcesLoader from '../ObjectsRendering/ResourcesLoader';
|
||||
import ResourcesLoader from '../ResourcesLoader';
|
||||
import ResourceSelector from '../ResourcesList/ResourceSelector';
|
||||
import ImageThumbnail from './ImageThumbnail';
|
||||
|
||||
@@ -10,6 +10,7 @@ export default ({
|
||||
resourceKind,
|
||||
resourceName,
|
||||
onChange,
|
||||
floatingLabelText,
|
||||
}) => {
|
||||
return (
|
||||
<div style={{ flex: 1, display: 'flex', alignItems: 'flex-end' }}>
|
||||
@@ -22,6 +23,7 @@ export default ({
|
||||
fullWidth
|
||||
initialResourceName={resourceName}
|
||||
onChange={onChange}
|
||||
floatingLabelText={floatingLabelText}
|
||||
/>
|
||||
</div>
|
||||
<ImageThumbnail
|
||||
|
@@ -7,7 +7,7 @@ import RenderedTextInstance from './Renderers/RenderedTextInstance';
|
||||
import RenderedShapePainterInstance from './Renderers/RenderedShapePainterInstance';
|
||||
import RenderedTextEntryInstance from './Renderers/RenderedTextEntryInstance';
|
||||
import PixiResourcesLoader from './PixiResourcesLoader';
|
||||
import ResourcesLoader from './ResourcesLoader';
|
||||
import ResourcesLoader from '../ResourcesLoader';
|
||||
|
||||
/**
|
||||
* A service containing functions that are called to render instances
|
||||
|
@@ -1,6 +1,7 @@
|
||||
// @flow
|
||||
import slugs from 'slugs';
|
||||
import PIXI from 'pixi.js';
|
||||
import ResourcesLoader from './ResourcesLoader';
|
||||
import ResourcesLoader from '../ResourcesLoader';
|
||||
import { loadFontFace } from '../Utils/FontFaceLoader';
|
||||
const gd = global.gd;
|
||||
|
||||
@@ -9,7 +10,7 @@ const loadedTextures = {};
|
||||
const invalidTexture = PIXI.Texture.fromImage('res/error48.png');
|
||||
|
||||
export default class PixiResourcesLoader {
|
||||
static _initializeTexture(resource, texture) {
|
||||
static _initializeTexture(resource: gdResource, texture: any) {
|
||||
if (resource.getKind() !== 'image') return;
|
||||
|
||||
const imageResource = gd.asImageResource(resource);
|
||||
@@ -18,7 +19,11 @@ export default class PixiResourcesLoader {
|
||||
}
|
||||
}
|
||||
|
||||
static loadTextures(project, onProgress, onComplete) {
|
||||
static loadTextures(
|
||||
project: gdProject,
|
||||
onProgress: (number, number) => void,
|
||||
onComplete: () => void
|
||||
) {
|
||||
const resourcesManager = project.getResourcesManager();
|
||||
const loader = PIXI.loader;
|
||||
|
||||
@@ -26,7 +31,7 @@ export default class PixiResourcesLoader {
|
||||
const allResources = {};
|
||||
resourcesList.forEach(resourceName => {
|
||||
const resource = resourcesManager.getResource(resourceName);
|
||||
const filename = ResourcesLoader.getResourceFullFilename(
|
||||
const filename = ResourcesLoader.getResourceFullUrl(
|
||||
project,
|
||||
resourceName
|
||||
);
|
||||
@@ -72,7 +77,7 @@ export default class PixiResourcesLoader {
|
||||
* should listen to PIXI.Texture `update` event, and refresh your object
|
||||
* if this event is triggered.
|
||||
*/
|
||||
static getPIXITexture(project, resourceName) {
|
||||
static getPIXITexture(project: gdProject, resourceName: string) {
|
||||
if (loadedTextures[resourceName]) {
|
||||
return loadedTextures[resourceName];
|
||||
}
|
||||
@@ -84,7 +89,7 @@ export default class PixiResourcesLoader {
|
||||
if (resource.getKind() !== 'image') return invalidTexture;
|
||||
|
||||
loadedTextures[resourceName] = PIXI.Texture.fromImage(
|
||||
ResourcesLoader.getResourceFullFilename(project, resourceName),
|
||||
ResourcesLoader.getResourceFullUrl(project, resourceName),
|
||||
true /* Treats request as cross-origin */
|
||||
);
|
||||
|
||||
@@ -100,14 +105,17 @@ export default class PixiResourcesLoader {
|
||||
* @returns a Promise that resolves with the font-family to be used
|
||||
* to render a text with the font.
|
||||
*/
|
||||
static loadFontFamily(project, fontFilename) {
|
||||
static loadFontFamily(
|
||||
project: gdProject,
|
||||
fontFilename: string
|
||||
): Promise<string> {
|
||||
// Avoid reloading a font if it's already cached
|
||||
if (loadedFontFamilies[fontFilename]) {
|
||||
return Promise.resolve(loadedFontFamilies[fontFilename]);
|
||||
}
|
||||
|
||||
const fontFamily = slugs(fontFilename);
|
||||
const fullFilename = ResourcesLoader.getFullFilename(project, fontFilename);
|
||||
const fullFilename = ResourcesLoader.getFullUrl(project, fontFilename);
|
||||
return loadFontFace(
|
||||
fontFamily,
|
||||
`url("${fullFilename}")`,
|
||||
@@ -124,7 +132,7 @@ export default class PixiResourcesLoader {
|
||||
* The font won't be loaded.
|
||||
* @returns The font-family to be used to render a text with the font.
|
||||
*/
|
||||
static getFontFamily(project, fontFilename) {
|
||||
static getFontFamily(project: gdProject, fontFilename: string) {
|
||||
if (loadedFontFamilies[fontFilename]) {
|
||||
return loadedFontFamilies[fontFilename];
|
||||
}
|
||||
|
@@ -376,7 +376,7 @@ RenderedPanelSpriteInstance.getThumbnail = function(
|
||||
) {
|
||||
const panelSprite = gd.asPanelSpriteObject(object);
|
||||
|
||||
return resourcesLoader.getResourceFullFilename(
|
||||
return resourcesLoader.getResourceFullUrl(
|
||||
project,
|
||||
panelSprite.getTexture()
|
||||
);
|
||||
|
@@ -69,7 +69,7 @@ RenderedSpriteInstance.getThumbnail = function(
|
||||
.getDirection(0)
|
||||
.getSprite(0)
|
||||
.getImageName();
|
||||
return resourcesLoader.getResourceFullFilename(project, imageName);
|
||||
return resourcesLoader.getResourceFullUrl(project, imageName);
|
||||
}
|
||||
|
||||
return 'res/unknown32.png';
|
||||
|
@@ -55,7 +55,7 @@ RenderedTiledSpriteInstance.getThumbnail = function(
|
||||
) {
|
||||
var tiledSprite = gd.asTiledSpriteObject(object);
|
||||
|
||||
return resourcesLoader.getResourceFullFilename(
|
||||
return resourcesLoader.getResourceFullUrl(
|
||||
project,
|
||||
tiledSprite.getTexture()
|
||||
);
|
||||
|
@@ -1,84 +0,0 @@
|
||||
import optionalRequire from '../Utils/OptionalRequire.js';
|
||||
const electron = optionalRequire('electron');
|
||||
const path = optionalRequire('path');
|
||||
|
||||
class FilenamesCache {
|
||||
constructor() {
|
||||
this.projectCache = {};
|
||||
}
|
||||
|
||||
_getProjectCache(project) {
|
||||
const cache = this.projectCache[project.ptr];
|
||||
if (!cache) {
|
||||
return (this.projectCache[project.ptr] = {});
|
||||
}
|
||||
|
||||
return cache;
|
||||
}
|
||||
|
||||
getSystemFilename(project, filename) {
|
||||
const cache = this._getProjectCache(project);
|
||||
return cache[filename];
|
||||
}
|
||||
|
||||
cacheSystemFilename(project, filename, systemFilename) {
|
||||
const cache = this._getProjectCache(project);
|
||||
return (cache[filename] = systemFilename);
|
||||
}
|
||||
}
|
||||
|
||||
export default class ResourceLoader {
|
||||
static _cache = new FilenamesCache();
|
||||
|
||||
static isURL(filename) {
|
||||
return (
|
||||
filename.indexOf('http://') === 0 ||
|
||||
filename.indexOf('https://') === 0 ||
|
||||
filename.indexOf('ftp://') === 0
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the fully qualified URL/filename for a filename relative to the project.
|
||||
*/
|
||||
static getFullFilename(project, filename) {
|
||||
const cachedSystemFilename = ResourceLoader._cache.getSystemFilename(
|
||||
project,
|
||||
filename
|
||||
);
|
||||
if (cachedSystemFilename) return cachedSystemFilename;
|
||||
|
||||
if (electron && !ResourceLoader.isURL(filename)) {
|
||||
// Support local filesystem with Electron
|
||||
const file = project.getProjectFile();
|
||||
const projectPath = path.dirname(file);
|
||||
const resourceAbsolutePath = path
|
||||
.resolve(projectPath, filename)
|
||||
.replace(/\\/g, '/');
|
||||
|
||||
console.info('Loading', resourceAbsolutePath);
|
||||
return this._cache.cacheSystemFilename(
|
||||
project,
|
||||
filename,
|
||||
'file://' + resourceAbsolutePath
|
||||
);
|
||||
}
|
||||
|
||||
return this._cache.cacheSystemFilename(project, filename, filename);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the fully qualified URL/filename associated with the given resource.
|
||||
*/
|
||||
static getResourceFullFilename(project, resourceName) {
|
||||
if (project.getResourcesManager().hasResource(resourceName)) {
|
||||
const resourceRelativePath = project
|
||||
.getResourcesManager()
|
||||
.getResource(resourceName)
|
||||
.getFile();
|
||||
return ResourceLoader.getFullFilename(project, resourceRelativePath);
|
||||
}
|
||||
|
||||
return resourceName;
|
||||
}
|
||||
}
|
25
newIDE/app/src/PlatformSpecificAssetsEditor/ImageResizer.js
Normal file
25
newIDE/app/src/PlatformSpecificAssetsEditor/ImageResizer.js
Normal file
@@ -0,0 +1,25 @@
|
||||
//@flow
|
||||
import optionalRequire from '../Utils/OptionalRequire';
|
||||
const Jimp = optionalRequire('jimp');
|
||||
|
||||
export const isResizeSupported = () => !!Jimp;
|
||||
|
||||
export const resizeImage = (
|
||||
inputFile: string,
|
||||
outputFile: string,
|
||||
{ width, height }: { width: number, height: number }
|
||||
): Promise<any> => {
|
||||
if (!Jimp) return Promise.resolve(false);
|
||||
|
||||
return Jimp.read(inputFile)
|
||||
.then(function(jimpImage) {
|
||||
return jimpImage.contain(width, height).write(outputFile);
|
||||
})
|
||||
.then(() => {
|
||||
return true;
|
||||
})
|
||||
.catch(function(err) {
|
||||
console.error(err);
|
||||
return false;
|
||||
});
|
||||
};
|
@@ -0,0 +1,255 @@
|
||||
// @flow
|
||||
import * as React from 'react';
|
||||
import path from 'path';
|
||||
import FlatButton from 'material-ui/FlatButton';
|
||||
import RaisedButton from 'material-ui/RaisedButton';
|
||||
import Dialog from '../UI/Dialog';
|
||||
import { Line } from '../UI/Grid';
|
||||
import ResourcesLoader from '../ResourcesLoader';
|
||||
import ResourceSelectorWithThumbnail from '../ObjectEditor/ResourceSelectorWithThumbnail';
|
||||
import {
|
||||
type ResourceSource,
|
||||
type ChooseResourceFunction,
|
||||
} from '../ResourcesList/ResourceSource.flow';
|
||||
import { resizeImage, isResizeSupported } from './ImageResizer';
|
||||
import { showErrorBox } from '../UI/Messages/MessageBox';
|
||||
const gd = global.gd;
|
||||
|
||||
type Props = {|
|
||||
project: gdProject,
|
||||
open: boolean,
|
||||
onClose: Function,
|
||||
onApply: Function,
|
||||
resourceSources: Array<ResourceSource>,
|
||||
onChooseResource: ChooseResourceFunction,
|
||||
|};
|
||||
|
||||
type State = {|
|
||||
androidIconResourceNames: Array<string>,
|
||||
iosIconResourceNames: Array<string>,
|
||||
|};
|
||||
|
||||
const androidSizes = [192, 144, 96, 72, 48, 36];
|
||||
const iosSizes = [
|
||||
180,
|
||||
167,
|
||||
152,
|
||||
144,
|
||||
120,
|
||||
114,
|
||||
100,
|
||||
80,
|
||||
76,
|
||||
72,
|
||||
60,
|
||||
58,
|
||||
57,
|
||||
50,
|
||||
40,
|
||||
29,
|
||||
];
|
||||
|
||||
export default class PlatformSpecificAssetsDialog extends React.Component<
|
||||
Props,
|
||||
State
|
||||
> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
this.state = this._loadFrom(props.project);
|
||||
}
|
||||
|
||||
_loadFrom(project: gdProject): State {
|
||||
return {
|
||||
androidIconResourceNames: androidSizes.map(size =>
|
||||
project.getPlatformSpecificAssets().get('android', `icon-${size}`)
|
||||
),
|
||||
iosIconResourceNames: iosSizes.map(size =>
|
||||
project.getPlatformSpecificAssets().get('ios', `icon-${size}`)
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
componentWillReceiveProps(newProps: Props) {
|
||||
if (
|
||||
(!this.props.open && newProps.open) ||
|
||||
(newProps.open && this.props.project !== newProps.project)
|
||||
) {
|
||||
this.setState(this._loadFrom(newProps.project));
|
||||
}
|
||||
}
|
||||
|
||||
_generateFromFile = () => {
|
||||
const { project, resourceSources, onChooseResource } = this.props;
|
||||
|
||||
const sources = resourceSources.filter(source => source.kind === 'image');
|
||||
if (!sources.length) return;
|
||||
|
||||
onChooseResource(sources[0].name, false).then(resources => {
|
||||
if (!resources.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
const resourcesManager = project.getResourcesManager();
|
||||
const projectPath = path.dirname(project.getProjectFile());
|
||||
const fullPath = path.resolve(projectPath, resources[0].getFile());
|
||||
|
||||
Promise.all([
|
||||
...androidSizes.map(size =>
|
||||
resizeImage(
|
||||
fullPath,
|
||||
path.join(projectPath, `android-icon-${size}.png`),
|
||||
{
|
||||
width: size,
|
||||
height: size,
|
||||
}
|
||||
)
|
||||
),
|
||||
...iosSizes.map(size =>
|
||||
resizeImage(
|
||||
fullPath,
|
||||
path.join(projectPath, `ios-icon-${size}.png`),
|
||||
{
|
||||
width: size,
|
||||
height: size,
|
||||
}
|
||||
)
|
||||
),
|
||||
]).then(results => {
|
||||
if (results.indexOf(false) !== -1) {
|
||||
showErrorBox('Some icons could not be generated!');
|
||||
return;
|
||||
}
|
||||
|
||||
const createOrUpdateResource = name => {
|
||||
if (!resourcesManager.hasResource(name)) {
|
||||
const imageResource = new gd.ImageResource();
|
||||
imageResource.setFile(name);
|
||||
imageResource.setName(name);
|
||||
|
||||
resourcesManager.addResource(imageResource);
|
||||
imageResource.delete();
|
||||
} else {
|
||||
resourcesManager.getResource(name).setFile(name);
|
||||
}
|
||||
};
|
||||
|
||||
androidSizes.forEach(size =>
|
||||
createOrUpdateResource(`android-icon-${size}.png`)
|
||||
);
|
||||
iosSizes.forEach(size =>
|
||||
createOrUpdateResource(`ios-icon-${size}.png`)
|
||||
);
|
||||
|
||||
ResourcesLoader.burstUrlsCache();
|
||||
setTimeout(() => {
|
||||
this.setState({
|
||||
androidIconResourceNames: androidSizes.map(
|
||||
size => `android-icon-${size}.png`
|
||||
),
|
||||
iosIconResourceNames: iosSizes.map(size => `ios-icon-${size}.png`),
|
||||
});
|
||||
}, 200 /* Let a bit of time so that image files can be found */);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
_onApply = () => {
|
||||
const { project } = this.props;
|
||||
const { androidIconResourceNames, iosIconResourceNames } = this.state;
|
||||
|
||||
androidSizes.forEach((size, index) => {
|
||||
project
|
||||
.getPlatformSpecificAssets()
|
||||
.set('android', `icon-${size}`, androidIconResourceNames[index]);
|
||||
});
|
||||
iosSizes.forEach((size, index) => {
|
||||
project
|
||||
.getPlatformSpecificAssets()
|
||||
.set('ios', `icon-${size}`, iosIconResourceNames[index]);
|
||||
});
|
||||
|
||||
this.props.onApply();
|
||||
};
|
||||
|
||||
render() {
|
||||
const actions = [
|
||||
<FlatButton
|
||||
label="Cancel"
|
||||
primary={false}
|
||||
onClick={this.props.onClose}
|
||||
/>,
|
||||
<FlatButton
|
||||
label="Apply"
|
||||
primary={true}
|
||||
keyboardFocused={true}
|
||||
onClick={this._onApply}
|
||||
/>,
|
||||
];
|
||||
const { project, resourceSources, onChooseResource } = this.props;
|
||||
const { androidIconResourceNames, iosIconResourceNames } = this.state;
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
actions={actions}
|
||||
open={this.props.open}
|
||||
onRequestClose={this.props.onClose}
|
||||
autoScrollBodyContent
|
||||
>
|
||||
<Line justifyContent="center">
|
||||
{isResizeSupported() ? (
|
||||
<RaisedButton
|
||||
primary
|
||||
label="Generate icons from a file"
|
||||
onClick={this._generateFromFile}
|
||||
/>
|
||||
) : (
|
||||
<p>
|
||||
Download GDevelop desktop version to generate the Android and iOS
|
||||
icons of your game.
|
||||
</p>
|
||||
)}
|
||||
</Line>
|
||||
<p>Android icons:</p>
|
||||
{androidSizes.map((size, index) => (
|
||||
<ResourceSelectorWithThumbnail
|
||||
key={size}
|
||||
floatingLabelText={`Android icon (${size}x${size} px)`}
|
||||
project={project}
|
||||
resourceSources={resourceSources}
|
||||
onChooseResource={onChooseResource}
|
||||
resourceKind="image"
|
||||
resourceName={androidIconResourceNames[index]}
|
||||
resourcesLoader={ResourcesLoader}
|
||||
onChange={resourceName => {
|
||||
const newIcons = [...androidIconResourceNames];
|
||||
newIcons[index] = resourceName;
|
||||
this.setState({
|
||||
androidIconResourceNames: newIcons,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
<p>iOS (iPhone and iPad) icons:</p>
|
||||
{iosSizes.map((size, index) => (
|
||||
<ResourceSelectorWithThumbnail
|
||||
key={size}
|
||||
floatingLabelText={`iOS icon (${size}x${size} px)`}
|
||||
project={project}
|
||||
resourceSources={resourceSources}
|
||||
onChooseResource={onChooseResource}
|
||||
resourceKind="image"
|
||||
resourceName={iosIconResourceNames[index]}
|
||||
resourcesLoader={ResourcesLoader}
|
||||
onChange={resourceName => {
|
||||
const newIcons = [...iosIconResourceNames];
|
||||
newIcons[index] = resourceName;
|
||||
this.setState({
|
||||
iosIconResourceNames: newIcons,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
}
|
@@ -1,25 +1,48 @@
|
||||
import React, { Component } from 'react';
|
||||
// @flow
|
||||
import * as React from 'react';
|
||||
import FlatButton from 'material-ui/FlatButton';
|
||||
import TextField from 'material-ui/TextField';
|
||||
import SelectField from 'material-ui/SelectField';
|
||||
import MenuItem from 'material-ui/MenuItem';
|
||||
import Dialog from '../UI/Dialog';
|
||||
|
||||
export default class ProjectPropertiesDialog extends Component {
|
||||
constructor(props) {
|
||||
type Props = {|
|
||||
project: gdProject,
|
||||
open: boolean,
|
||||
onClose: Function,
|
||||
onApply: Function,
|
||||
|};
|
||||
|
||||
type State = {|
|
||||
windowDefaultWidth: number,
|
||||
windowDefaultHeight: number,
|
||||
name: string,
|
||||
author: string,
|
||||
packageName: string,
|
||||
orientation: string,
|
||||
|};
|
||||
|
||||
export default class ProjectPropertiesDialog extends React.Component<
|
||||
Props,
|
||||
State
|
||||
> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
this.state = { ...this._loadFrom(props.project) };
|
||||
this.state = this._loadFrom(props.project);
|
||||
}
|
||||
|
||||
_loadFrom(project) {
|
||||
_loadFrom(project: gdProject): State {
|
||||
return {
|
||||
windowDefaultWidth: project.getMainWindowDefaultWidth(),
|
||||
windowDefaultHeight: project.getMainWindowDefaultHeight(),
|
||||
name: project.getName(),
|
||||
author: project.getAuthor(),
|
||||
packageName: project.getPackageName(),
|
||||
orientation: project.getOrientation(),
|
||||
};
|
||||
}
|
||||
|
||||
componentWillReceiveProps(newProps) {
|
||||
componentWillReceiveProps(newProps: Props) {
|
||||
if (
|
||||
(!this.props.open && newProps.open) ||
|
||||
(newProps.open && this.props.project !== newProps.project)
|
||||
@@ -30,12 +53,22 @@ export default class ProjectPropertiesDialog extends Component {
|
||||
|
||||
_onApply = () => {
|
||||
const { project } = this.props;
|
||||
project.setDefaultWidth(this.state.windowDefaultWidth);
|
||||
project.setDefaultHeight(this.state.windowDefaultHeight);
|
||||
project.setName(this.state.name);
|
||||
project.setAuthor(this.state.author);
|
||||
project.setPackageName(this.state.packageName);
|
||||
if (this.props.onApply) this.props.onApply();
|
||||
const {
|
||||
windowDefaultWidth,
|
||||
windowDefaultHeight,
|
||||
name,
|
||||
author,
|
||||
packageName,
|
||||
orientation,
|
||||
} = this.state;
|
||||
project.setDefaultWidth(windowDefaultWidth);
|
||||
project.setDefaultHeight(windowDefaultHeight);
|
||||
project.setName(name);
|
||||
project.setAuthor(author);
|
||||
project.setPackageName(packageName);
|
||||
project.setOrientation(orientation);
|
||||
|
||||
this.props.onApply();
|
||||
};
|
||||
|
||||
render() {
|
||||
@@ -52,6 +85,14 @@ export default class ProjectPropertiesDialog extends Component {
|
||||
onClick={this._onApply}
|
||||
/>,
|
||||
];
|
||||
const {
|
||||
name,
|
||||
windowDefaultWidth,
|
||||
windowDefaultHeight,
|
||||
author,
|
||||
packageName,
|
||||
orientation,
|
||||
} = this.state;
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
@@ -59,20 +100,19 @@ export default class ProjectPropertiesDialog extends Component {
|
||||
open={this.props.open}
|
||||
onRequestClose={this.props.onClose}
|
||||
autoScrollBodyContent={true}
|
||||
contentStyle={{ width: '350px' }}
|
||||
>
|
||||
<TextField
|
||||
floatingLabelText="Game name"
|
||||
fullWidth
|
||||
type="text"
|
||||
value={this.state.name}
|
||||
value={name}
|
||||
onChange={(e, value) => this.setState({ name: value })}
|
||||
/>
|
||||
<TextField
|
||||
floatingLabelText="Game's window width"
|
||||
fullWidth
|
||||
type="number"
|
||||
value={this.state.windowDefaultWidth}
|
||||
value={windowDefaultWidth}
|
||||
onChange={(e, value) =>
|
||||
this.setState({
|
||||
windowDefaultWidth: Math.max(0, parseInt(value, 10)),
|
||||
@@ -82,7 +122,7 @@ export default class ProjectPropertiesDialog extends Component {
|
||||
floatingLabelText="Game's window height"
|
||||
fullWidth
|
||||
type="number"
|
||||
value={this.state.windowDefaultHeight}
|
||||
value={windowDefaultHeight}
|
||||
onChange={(e, value) =>
|
||||
this.setState({
|
||||
windowDefaultHeight: Math.max(0, parseInt(value, 10)),
|
||||
@@ -93,7 +133,7 @@ export default class ProjectPropertiesDialog extends Component {
|
||||
fullWidth
|
||||
hintText="Your name"
|
||||
type="text"
|
||||
value={this.state.author}
|
||||
value={author}
|
||||
onChange={(e, value) => this.setState({ author: value })}
|
||||
/>
|
||||
<TextField
|
||||
@@ -101,16 +141,19 @@ export default class ProjectPropertiesDialog extends Component {
|
||||
fullWidth
|
||||
hintText="com.example.mygame"
|
||||
type="text"
|
||||
value={this.state.packageName}
|
||||
value={packageName}
|
||||
onChange={(e, value) => this.setState({ packageName: value })}
|
||||
/>
|
||||
<TextField
|
||||
floatingLabelText="Icon"
|
||||
<SelectField
|
||||
fullWidth
|
||||
type="text"
|
||||
disabled
|
||||
value="Coming soon"
|
||||
/>
|
||||
floatingLabelText="Device orientation (for iOS and Android)"
|
||||
value={orientation}
|
||||
onChange={(e, i, value) => this.setState({orientation: value})}
|
||||
>
|
||||
<MenuItem value="default" primaryText="Platform default" />
|
||||
<MenuItem value="landscape" primaryText="Landscape" />
|
||||
<MenuItem value="portrait" primaryText="Portrait" />
|
||||
</SelectField>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
@@ -161,17 +161,17 @@ const Item = muiThemeable()(ThemableItem);
|
||||
|
||||
const AddItem = makeAddItem(ListItem);
|
||||
|
||||
type Props = {
|
||||
type Props = {|
|
||||
project: gdProject,
|
||||
onDeleteLayout: (gdLayout) => void,
|
||||
onDeleteExternalEvents: (gdExternalEvents) => void,
|
||||
onDeleteExternalLayout: (gdExternalLayout) => void,
|
||||
onDeleteLayout: gdLayout => void,
|
||||
onDeleteExternalEvents: gdExternalEvents => void,
|
||||
onDeleteExternalLayout: gdExternalLayout => void,
|
||||
onRenameLayout: (string, string) => void,
|
||||
onRenameExternalEvents: (string, string) => void,
|
||||
onRenameExternalLayout: (string, string) => void,
|
||||
onOpenLayout: (string) => void,
|
||||
onOpenExternalEvents: (string) => void,
|
||||
onOpenExternalLayout: (string) => void,
|
||||
onOpenLayout: string => void,
|
||||
onOpenExternalEvents: string => void,
|
||||
onOpenExternalLayout: string => void,
|
||||
onSaveProject: () => void,
|
||||
onCloseProject: () => void,
|
||||
onExportProject: () => void,
|
||||
@@ -180,14 +180,15 @@ type Props = {
|
||||
onAddLayout: () => void,
|
||||
onAddExternalEvents: () => void,
|
||||
onAddExternalLayout: () => void,
|
||||
};
|
||||
onOpenPlatformSpecificAssets: () => void,
|
||||
|};
|
||||
|
||||
type State = {|
|
||||
renamedItemKind: ?string,
|
||||
renamedItemName: string,
|
||||
searchText: string,
|
||||
projectPropertiesDialogOpen: boolean,
|
||||
variablesEditorOpen: boolean,
|
||||
renamedItemName: string,
|
||||
searchText: string,
|
||||
projectPropertiesDialogOpen: boolean,
|
||||
variablesEditorOpen: boolean,
|
||||
|};
|
||||
|
||||
export default class ProjectManager extends React.Component<Props, State> {
|
||||
@@ -385,6 +386,12 @@ export default class ProjectManager extends React.Component<Props, State> {
|
||||
leftIcon={<ListIcon src="res/ribbon_default/editname32.png" />}
|
||||
onClick={() => this.setState({ variablesEditorOpen: true })}
|
||||
/>,
|
||||
<ListItem
|
||||
key="icons"
|
||||
primaryText="Icons"
|
||||
leftIcon={<ListIcon src="res/ribbon_default/image32.png" />}
|
||||
onClick={() => this.props.onOpenPlatformSpecificAssets()}
|
||||
/>,
|
||||
<ListItem
|
||||
key="resources"
|
||||
primaryText="Resources"
|
||||
|
@@ -4,7 +4,7 @@ import Paper from 'material-ui/Paper';
|
||||
import EmptyMessage from '../../UI/EmptyMessage';
|
||||
import PropertiesEditor from '../../PropertiesEditor';
|
||||
import ImagePreview from '../../ObjectEditor/ImagePreview'; //TODO: Move ImagePreview out of ObjectEditor
|
||||
import ResourceLoader from '../../ObjectsRendering/ResourcesLoader';
|
||||
import ResourcesLoader from '../../ResourcesLoader';
|
||||
|
||||
const styles = {
|
||||
container: {
|
||||
@@ -24,7 +24,7 @@ const styles = {
|
||||
|
||||
type Props = {|
|
||||
project: gdProject,
|
||||
resourcesLoader: ResourceLoader,
|
||||
resourcesLoader: typeof ResourcesLoader,
|
||||
resources: Array<gdResource>,
|
||||
|};
|
||||
|
||||
|
@@ -5,7 +5,7 @@ import ResourcePropertiesEditor from './ResourcePropertiesEditor';
|
||||
import Toolbar from './Toolbar';
|
||||
import EditorMosaic, { MosaicWindow } from '../UI/EditorMosaic';
|
||||
import InfoBar from '../UI/Messages/InfoBar';
|
||||
import ResourcesLoader from '../ObjectsRendering/ResourcesLoader';
|
||||
import ResourcesLoader from '../ResourcesLoader';
|
||||
|
||||
const styles = {
|
||||
container: {
|
||||
@@ -108,8 +108,6 @@ export default class InstancesFullEditor extends React.Component<Props, State> {
|
||||
const { project, onRenameResource } = this.props;
|
||||
const { selectedResource } = this.state;
|
||||
|
||||
console.log(selectedResource);
|
||||
|
||||
const editors = {
|
||||
properties: (
|
||||
<MosaicWindow
|
||||
|
@@ -20,6 +20,14 @@ export default class ResourceSelector extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.initialResourceName !== this.props.initialResourceName) {
|
||||
this.setState({
|
||||
resourceName: nextProps.initialResourceName || '',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
_getDefaultItems() {
|
||||
const sources = this.props.resourceSources || [];
|
||||
return [
|
||||
|
14
newIDE/app/src/ResourcesList/ResourceSource.flow.js
Normal file
14
newIDE/app/src/ResourcesList/ResourceSource.flow.js
Normal file
@@ -0,0 +1,14 @@
|
||||
// @flow
|
||||
import * as React from 'react';
|
||||
|
||||
export type ResourceSource = {
|
||||
name: string,
|
||||
displayName: string,
|
||||
kind: 'image' | 'audio',
|
||||
component: React.Component<*, *>,
|
||||
};
|
||||
|
||||
export type ChooseResourceFunction = (
|
||||
sourceName: string,
|
||||
multiSelection: boolean
|
||||
) => Promise<Array<gdResource>>;
|
107
newIDE/app/src/ResourcesLoader/index.js
Normal file
107
newIDE/app/src/ResourcesLoader/index.js
Normal file
@@ -0,0 +1,107 @@
|
||||
// @flow
|
||||
import optionalRequire from '../Utils/OptionalRequire.js';
|
||||
const electron = optionalRequire('electron');
|
||||
const path = optionalRequire('path');
|
||||
|
||||
class UrlsCache {
|
||||
projectCache = {};
|
||||
|
||||
_getProjectCache(project: gdProject) {
|
||||
const cache = this.projectCache[project.ptr];
|
||||
if (!cache) {
|
||||
return (this.projectCache[project.ptr] = {});
|
||||
}
|
||||
|
||||
return cache;
|
||||
}
|
||||
|
||||
getCachedUrl(project: gdProject, filename: string) {
|
||||
const cache = this._getProjectCache(project);
|
||||
return cache[filename];
|
||||
}
|
||||
|
||||
cacheUrl(project: gdProject, url: string) {
|
||||
const cache = this._getProjectCache(project);
|
||||
return (cache[url] = url);
|
||||
}
|
||||
|
||||
cacheLocalFileUrl(
|
||||
project: gdProject,
|
||||
filename: string,
|
||||
systemFilename: string
|
||||
) {
|
||||
const cache = this._getProjectCache(project);
|
||||
|
||||
// The URL is cached with an extra "cache-bursting" parameter.
|
||||
// If the cache is emptied or changed, local files will have another
|
||||
// value for this parameter, forcing the browser to reload the images.
|
||||
return (cache[filename] = `${systemFilename}?cache=${Date.now()}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A class globally used in the whole IDE to get URLs to resources of games
|
||||
* (notably images).
|
||||
*/
|
||||
export default class ResourcesLoader {
|
||||
static _cache = new UrlsCache();
|
||||
|
||||
static isLocalFile(filename: string): boolean {
|
||||
return (
|
||||
filename.indexOf('data:') !== 0 &&
|
||||
filename.indexOf('http://') !== 0 &&
|
||||
filename.indexOf('https://') !== 0 &&
|
||||
filename.indexOf('ftp://') !== 0
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-create a new cache for URLs. Call this to force local
|
||||
* file to be loaded again.
|
||||
*/
|
||||
static burstUrlsCache() {
|
||||
ResourcesLoader._cache = new UrlsCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the fully qualified URL/filename for a filename relative to the project.
|
||||
*/
|
||||
static getFullUrl(project: gdProject, filename: string) {
|
||||
const cachedUrl = ResourcesLoader._cache.getCachedUrl(project, filename);
|
||||
if (cachedUrl) return cachedUrl;
|
||||
|
||||
if (electron && ResourcesLoader.isLocalFile(filename)) {
|
||||
// Support local filesystem with Electron
|
||||
const file = project.getProjectFile();
|
||||
const projectPath = path.dirname(file);
|
||||
const resourceAbsolutePath = path
|
||||
.resolve(projectPath, filename)
|
||||
.replace(/\\/g, '/');
|
||||
|
||||
console.info('Caching resolved local filename:', resourceAbsolutePath);
|
||||
return this._cache.cacheLocalFileUrl(
|
||||
project,
|
||||
filename,
|
||||
'file://' + resourceAbsolutePath
|
||||
);
|
||||
}
|
||||
|
||||
// URLs to non local files are unchanged
|
||||
return this._cache.cacheUrl(project, filename);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the fully qualified URL/filename associated with the given resource.
|
||||
*/
|
||||
static getResourceFullUrl(project: gdProject, resourceName: string) {
|
||||
if (project.getResourcesManager().hasResource(resourceName)) {
|
||||
const resourceRelativePath = project
|
||||
.getResourcesManager()
|
||||
.getResource(resourceName)
|
||||
.getFile();
|
||||
return ResourcesLoader.getFullUrl(project, resourceRelativePath);
|
||||
}
|
||||
|
||||
return resourceName;
|
||||
}
|
||||
}
|
@@ -12,7 +12,7 @@ export type Build = {
|
||||
bucket?: string,
|
||||
logsKey?: string,
|
||||
apkKey?: string,
|
||||
status: 'pending' | 'complete' | 'errored',
|
||||
status: 'pending' | 'complete' | 'error',
|
||||
type: 'cordova-build',
|
||||
createdAt: number,
|
||||
updatedAt: number,
|
||||
|
@@ -43,7 +43,7 @@ import muiDecorator from './MuiDecorator';
|
||||
import paperDecorator from './PaperDecorator';
|
||||
import ValueStateHolder from './ValueStateHolder';
|
||||
import DragDropContextProvider from '../Utils/DragDropHelpers/DragDropContextProvider';
|
||||
import ResourcesLoader from '../ObjectsRendering/ResourcesLoader';
|
||||
import ResourcesLoader from '../ResourcesLoader';
|
||||
import VariablesList from '../VariablesList';
|
||||
import ExpressionSelector from '../EventsSheet/InstructionEditor/InstructionOrExpressionSelector/ExpressionSelector';
|
||||
import InstructionSelector from '../EventsSheet/InstructionEditor/InstructionOrExpressionSelector/InstructionSelector';
|
||||
|
592
newIDE/electron-app/app/package-lock.json
generated
592
newIDE/electron-app/app/package-lock.json
generated
@@ -1,9 +1,20 @@
|
||||
{
|
||||
"name": "gdevelop",
|
||||
"version": "5.0.0-beta21",
|
||||
"version": "5.0.0-beta24",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"ajv": {
|
||||
"version": "5.5.2",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
|
||||
"integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=",
|
||||
"requires": {
|
||||
"co": "4.6.0",
|
||||
"fast-deep-equal": "1.0.0",
|
||||
"fast-json-stable-stringify": "2.0.0",
|
||||
"json-schema-traverse": "0.3.1"
|
||||
}
|
||||
},
|
||||
"archiver": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/archiver/-/archiver-2.1.1.tgz",
|
||||
@@ -40,6 +51,16 @@
|
||||
"sprintf-js": "1.0.3"
|
||||
}
|
||||
},
|
||||
"asn1": {
|
||||
"version": "0.2.3",
|
||||
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz",
|
||||
"integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y="
|
||||
},
|
||||
"assert-plus": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
|
||||
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
|
||||
},
|
||||
"async": {
|
||||
"version": "2.6.0",
|
||||
"resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz",
|
||||
@@ -48,6 +69,11 @@
|
||||
"lodash": "4.17.4"
|
||||
}
|
||||
},
|
||||
"asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
|
||||
},
|
||||
"aws-sdk": {
|
||||
"version": "2.181.0",
|
||||
"resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.181.0.tgz",
|
||||
@@ -66,6 +92,16 @@
|
||||
"xmlbuilder": "4.2.1"
|
||||
}
|
||||
},
|
||||
"aws-sign2": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
|
||||
"integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg="
|
||||
},
|
||||
"aws4": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz",
|
||||
"integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4="
|
||||
},
|
||||
"balanced-match": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
||||
@@ -76,6 +112,20 @@
|
||||
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.1.tgz",
|
||||
"integrity": "sha512-dwVUVIXsBZXwTuwnXI9RK8sBmgq09NDHzyR9SAph9eqk76gKK2JSQmZARC2zRC81JC2QTtxD0ARU5qTS25gIGw=="
|
||||
},
|
||||
"bcrypt-pbkdf": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz",
|
||||
"integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"tweetnacl": "0.14.5"
|
||||
}
|
||||
},
|
||||
"bignumber.js": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-2.4.0.tgz",
|
||||
"integrity": "sha1-g4qZLan51zfg9LLbC+YrsJ3Qxeg="
|
||||
},
|
||||
"bl": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/bl/-/bl-1.2.1.tgz",
|
||||
@@ -97,6 +147,19 @@
|
||||
"bluebird": "3.5.1"
|
||||
}
|
||||
},
|
||||
"bmp-js": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/bmp-js/-/bmp-js-0.0.3.tgz",
|
||||
"integrity": "sha1-ZBE+nHzxICs3btYHvzBibr5XsYo="
|
||||
},
|
||||
"boom": {
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz",
|
||||
"integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=",
|
||||
"requires": {
|
||||
"hoek": "4.2.0"
|
||||
}
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.8",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz",
|
||||
@@ -121,6 +184,11 @@
|
||||
"resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
|
||||
"integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI="
|
||||
},
|
||||
"buffer-equal": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.1.tgz",
|
||||
"integrity": "sha1-kbx0sR6kBbyRa8aqkI+q+ltKrEs="
|
||||
},
|
||||
"builder-util-runtime": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-4.0.1.tgz",
|
||||
@@ -139,6 +207,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"caseless": {
|
||||
"version": "0.12.0",
|
||||
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
|
||||
"integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
|
||||
},
|
||||
"cipher-base": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz",
|
||||
@@ -148,6 +221,19 @@
|
||||
"safe-buffer": "5.1.1"
|
||||
}
|
||||
},
|
||||
"co": {
|
||||
"version": "4.6.0",
|
||||
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
|
||||
"integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ="
|
||||
},
|
||||
"combined-stream": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz",
|
||||
"integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=",
|
||||
"requires": {
|
||||
"delayed-stream": "1.0.0"
|
||||
}
|
||||
},
|
||||
"compress-commons": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-1.2.2.tgz",
|
||||
@@ -207,6 +293,32 @@
|
||||
"sha.js": "2.4.9"
|
||||
}
|
||||
},
|
||||
"cryptiles": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz",
|
||||
"integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=",
|
||||
"requires": {
|
||||
"boom": "5.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"boom": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz",
|
||||
"integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==",
|
||||
"requires": {
|
||||
"hoek": "4.2.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"dashdash": {
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
|
||||
"integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
|
||||
"requires": {
|
||||
"assert-plus": "1.0.0"
|
||||
}
|
||||
},
|
||||
"debug": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
|
||||
@@ -215,11 +327,30 @@
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
|
||||
},
|
||||
"dom-walk": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.1.tgz",
|
||||
"integrity": "sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg="
|
||||
},
|
||||
"dotenv": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-4.0.0.tgz",
|
||||
"integrity": "sha1-hk7xN5rO1Vzm+V3r7NzhefegzR0="
|
||||
},
|
||||
"ecc-jsbn": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz",
|
||||
"integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"jsbn": "0.1.1"
|
||||
}
|
||||
},
|
||||
"electron-editor-context-menu": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/electron-editor-context-menu/-/electron-editor-context-menu-1.1.1.tgz",
|
||||
@@ -282,6 +413,11 @@
|
||||
"once": "1.4.0"
|
||||
}
|
||||
},
|
||||
"es6-promise": {
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz",
|
||||
"integrity": "sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM="
|
||||
},
|
||||
"esprima": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz",
|
||||
@@ -292,6 +428,59 @@
|
||||
"resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz",
|
||||
"integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ="
|
||||
},
|
||||
"exif-parser": {
|
||||
"version": "0.1.12",
|
||||
"resolved": "https://registry.npmjs.org/exif-parser/-/exif-parser-0.1.12.tgz",
|
||||
"integrity": "sha1-WKnS1ywCwfbwKg70qRZicrd2CSI="
|
||||
},
|
||||
"extend": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz",
|
||||
"integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ="
|
||||
},
|
||||
"extsprintf": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
|
||||
"integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
|
||||
},
|
||||
"fast-deep-equal": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz",
|
||||
"integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8="
|
||||
},
|
||||
"fast-json-stable-stringify": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
|
||||
"integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I="
|
||||
},
|
||||
"file-type": {
|
||||
"version": "3.9.0",
|
||||
"resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz",
|
||||
"integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek="
|
||||
},
|
||||
"for-each": {
|
||||
"version": "0.3.2",
|
||||
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.2.tgz",
|
||||
"integrity": "sha1-LEBFC5NI6X8oEyJZO6lnBLmr1NQ=",
|
||||
"requires": {
|
||||
"is-function": "1.0.1"
|
||||
}
|
||||
},
|
||||
"forever-agent": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
|
||||
"integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
|
||||
},
|
||||
"form-data": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.1.tgz",
|
||||
"integrity": "sha1-b7lPvXGIUwbXPRXMSX/kzE7NRL8=",
|
||||
"requires": {
|
||||
"asynckit": "0.4.0",
|
||||
"combined-stream": "1.0.5",
|
||||
"mime-types": "2.1.17"
|
||||
}
|
||||
},
|
||||
"fs-extra": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-3.0.1.tgz",
|
||||
@@ -336,6 +525,14 @@
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
|
||||
},
|
||||
"getpass": {
|
||||
"version": "0.1.7",
|
||||
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
|
||||
"integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
|
||||
"requires": {
|
||||
"assert-plus": "1.0.0"
|
||||
}
|
||||
},
|
||||
"glob": {
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
|
||||
@@ -349,11 +546,34 @@
|
||||
"path-is-absolute": "1.0.1"
|
||||
}
|
||||
},
|
||||
"global": {
|
||||
"version": "4.3.2",
|
||||
"resolved": "https://registry.npmjs.org/global/-/global-4.3.2.tgz",
|
||||
"integrity": "sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8=",
|
||||
"requires": {
|
||||
"min-document": "2.19.0",
|
||||
"process": "0.5.2"
|
||||
}
|
||||
},
|
||||
"graceful-fs": {
|
||||
"version": "4.1.11",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
|
||||
"integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg="
|
||||
},
|
||||
"har-schema": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
|
||||
"integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI="
|
||||
},
|
||||
"har-validator": {
|
||||
"version": "5.0.3",
|
||||
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz",
|
||||
"integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=",
|
||||
"requires": {
|
||||
"ajv": "5.5.2",
|
||||
"har-schema": "2.0.0"
|
||||
}
|
||||
},
|
||||
"hash-base": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz",
|
||||
@@ -362,6 +582,32 @@
|
||||
"inherits": "2.0.3"
|
||||
}
|
||||
},
|
||||
"hawk": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz",
|
||||
"integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==",
|
||||
"requires": {
|
||||
"boom": "4.3.1",
|
||||
"cryptiles": "3.1.2",
|
||||
"hoek": "4.2.0",
|
||||
"sntp": "2.1.0"
|
||||
}
|
||||
},
|
||||
"hoek": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz",
|
||||
"integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ=="
|
||||
},
|
||||
"http-signature": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
|
||||
"integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
|
||||
"requires": {
|
||||
"assert-plus": "1.0.0",
|
||||
"jsprim": "1.4.1",
|
||||
"sshpk": "1.13.1"
|
||||
}
|
||||
},
|
||||
"ieee754": {
|
||||
"version": "1.1.8",
|
||||
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz",
|
||||
@@ -381,16 +627,64 @@
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
||||
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
|
||||
},
|
||||
"ip-regex": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-1.0.3.tgz",
|
||||
"integrity": "sha1-3FiQdvZZ9BnCIgOaMzFvHHOH7/0="
|
||||
},
|
||||
"is-function": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.1.tgz",
|
||||
"integrity": "sha1-Es+5i2W1fdPRk6MSH19uL0N2ArU="
|
||||
},
|
||||
"is-typedarray": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
|
||||
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
|
||||
},
|
||||
"isarray": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
||||
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
|
||||
},
|
||||
"isstream": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
|
||||
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
|
||||
},
|
||||
"jimp": {
|
||||
"version": "0.2.28",
|
||||
"resolved": "https://registry.npmjs.org/jimp/-/jimp-0.2.28.tgz",
|
||||
"integrity": "sha1-3VKak3GQ9ClXp5N9Gsw6d2KZbqI=",
|
||||
"requires": {
|
||||
"bignumber.js": "2.4.0",
|
||||
"bmp-js": "0.0.3",
|
||||
"es6-promise": "3.3.1",
|
||||
"exif-parser": "0.1.12",
|
||||
"file-type": "3.9.0",
|
||||
"jpeg-js": "0.2.0",
|
||||
"load-bmfont": "1.3.0",
|
||||
"mime": "1.6.0",
|
||||
"mkdirp": "0.5.1",
|
||||
"pixelmatch": "4.0.2",
|
||||
"pngjs": "3.3.1",
|
||||
"read-chunk": "1.0.1",
|
||||
"request": "2.83.0",
|
||||
"stream-to-buffer": "0.1.0",
|
||||
"tinycolor2": "1.4.1",
|
||||
"url-regex": "3.2.0"
|
||||
}
|
||||
},
|
||||
"jmespath": {
|
||||
"version": "0.15.0",
|
||||
"resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz",
|
||||
"integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc="
|
||||
},
|
||||
"jpeg-js": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.2.0.tgz",
|
||||
"integrity": "sha1-U+RI7J0mPmgyZkZ+lELSxaLvVII="
|
||||
},
|
||||
"js-yaml": {
|
||||
"version": "3.10.0",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz",
|
||||
@@ -400,6 +694,27 @@
|
||||
"esprima": "4.0.0"
|
||||
}
|
||||
},
|
||||
"jsbn": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
|
||||
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
|
||||
"optional": true
|
||||
},
|
||||
"json-schema": {
|
||||
"version": "0.2.3",
|
||||
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
|
||||
"integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM="
|
||||
},
|
||||
"json-schema-traverse": {
|
||||
"version": "0.3.1",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz",
|
||||
"integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A="
|
||||
},
|
||||
"json-stringify-safe": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
|
||||
"integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
|
||||
},
|
||||
"jsonfile": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-3.0.1.tgz",
|
||||
@@ -408,6 +723,17 @@
|
||||
"graceful-fs": "4.1.11"
|
||||
}
|
||||
},
|
||||
"jsprim": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
|
||||
"integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
|
||||
"requires": {
|
||||
"assert-plus": "1.0.0",
|
||||
"extsprintf": "1.3.0",
|
||||
"json-schema": "0.2.3",
|
||||
"verror": "1.10.0"
|
||||
}
|
||||
},
|
||||
"lazy-val": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/lazy-val/-/lazy-val-1.0.3.tgz",
|
||||
@@ -421,6 +747,20 @@
|
||||
"readable-stream": "2.3.3"
|
||||
}
|
||||
},
|
||||
"load-bmfont": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/load-bmfont/-/load-bmfont-1.3.0.tgz",
|
||||
"integrity": "sha1-u358cQ3mvK/LE8s7jIHgwBMey8k=",
|
||||
"requires": {
|
||||
"buffer-equal": "0.0.1",
|
||||
"mime": "1.6.0",
|
||||
"parse-bmfont-ascii": "1.0.6",
|
||||
"parse-bmfont-binary": "1.0.6",
|
||||
"parse-bmfont-xml": "1.1.3",
|
||||
"xhr": "2.4.1",
|
||||
"xtend": "4.0.1"
|
||||
}
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.4",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz",
|
||||
@@ -461,6 +801,32 @@
|
||||
"resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz",
|
||||
"integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ="
|
||||
},
|
||||
"mime": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
|
||||
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
|
||||
},
|
||||
"mime-db": {
|
||||
"version": "1.30.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz",
|
||||
"integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE="
|
||||
},
|
||||
"mime-types": {
|
||||
"version": "2.1.17",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz",
|
||||
"integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=",
|
||||
"requires": {
|
||||
"mime-db": "1.30.0"
|
||||
}
|
||||
},
|
||||
"min-document": {
|
||||
"version": "2.19.0",
|
||||
"resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz",
|
||||
"integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=",
|
||||
"requires": {
|
||||
"dom-walk": "0.1.1"
|
||||
}
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
||||
@@ -474,6 +840,21 @@
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
|
||||
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
|
||||
},
|
||||
"mkdirp": {
|
||||
"version": "0.5.1",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
|
||||
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
|
||||
"requires": {
|
||||
"minimist": "0.0.8"
|
||||
},
|
||||
"dependencies": {
|
||||
"minimist": {
|
||||
"version": "0.0.8",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
|
||||
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
|
||||
}
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
@@ -487,6 +868,11 @@
|
||||
"remove-trailing-separator": "1.1.0"
|
||||
}
|
||||
},
|
||||
"oauth-sign": {
|
||||
"version": "0.8.2",
|
||||
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz",
|
||||
"integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM="
|
||||
},
|
||||
"once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
@@ -495,11 +881,62 @@
|
||||
"wrappy": "1.0.2"
|
||||
}
|
||||
},
|
||||
"parse-bmfont-ascii": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/parse-bmfont-ascii/-/parse-bmfont-ascii-1.0.6.tgz",
|
||||
"integrity": "sha1-Eaw8P/WPfCAgqyJ2kHkQjU36AoU="
|
||||
},
|
||||
"parse-bmfont-binary": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/parse-bmfont-binary/-/parse-bmfont-binary-1.0.6.tgz",
|
||||
"integrity": "sha1-0Di0dtPp3Z2x4RoLDlOiJ5K2kAY="
|
||||
},
|
||||
"parse-bmfont-xml": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/parse-bmfont-xml/-/parse-bmfont-xml-1.1.3.tgz",
|
||||
"integrity": "sha1-1rZqNxr9OcUAfZ8O6yYqTyzOe3w=",
|
||||
"requires": {
|
||||
"xml-parse-from-string": "1.0.1",
|
||||
"xml2js": "0.4.17"
|
||||
}
|
||||
},
|
||||
"parse-headers": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.1.tgz",
|
||||
"integrity": "sha1-aug6eqJanZtwCswoaYzR8e1+lTY=",
|
||||
"requires": {
|
||||
"for-each": "0.3.2",
|
||||
"trim": "0.0.1"
|
||||
}
|
||||
},
|
||||
"path-is-absolute": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
|
||||
},
|
||||
"performance-now": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
|
||||
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
|
||||
},
|
||||
"pixelmatch": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/pixelmatch/-/pixelmatch-4.0.2.tgz",
|
||||
"integrity": "sha1-j0fc7FARtHe2fbA8JDvB8wheiFQ=",
|
||||
"requires": {
|
||||
"pngjs": "3.3.1"
|
||||
}
|
||||
},
|
||||
"pngjs": {
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.3.1.tgz",
|
||||
"integrity": "sha512-ggXCTsqHRIsGMkHlCEhbHhUmNTA2r1lpkE0NL4Q9S8spkXbm4vE9TVmPso2AGYn90Gltdz8W5CyzhcIGg2Gejg=="
|
||||
},
|
||||
"process": {
|
||||
"version": "0.5.2",
|
||||
"resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz",
|
||||
"integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8="
|
||||
},
|
||||
"process-nextick-args": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
|
||||
@@ -510,11 +947,21 @@
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
|
||||
"integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0="
|
||||
},
|
||||
"qs": {
|
||||
"version": "6.5.1",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz",
|
||||
"integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A=="
|
||||
},
|
||||
"querystring": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
|
||||
"integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA="
|
||||
},
|
||||
"read-chunk": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/read-chunk/-/read-chunk-1.0.1.tgz",
|
||||
"integrity": "sha1-X2jKswfmY/GZk1J9m1icrORmEZQ="
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz",
|
||||
@@ -552,6 +999,35 @@
|
||||
"resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
|
||||
"integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8="
|
||||
},
|
||||
"request": {
|
||||
"version": "2.83.0",
|
||||
"resolved": "https://registry.npmjs.org/request/-/request-2.83.0.tgz",
|
||||
"integrity": "sha512-lR3gD69osqm6EYLk9wB/G1W/laGWjzH90t1vEa2xuxHD5KUrSzp9pUSfTm+YC5Nxt2T8nMPEvKlhbQayU7bgFw==",
|
||||
"requires": {
|
||||
"aws-sign2": "0.7.0",
|
||||
"aws4": "1.6.0",
|
||||
"caseless": "0.12.0",
|
||||
"combined-stream": "1.0.5",
|
||||
"extend": "3.0.1",
|
||||
"forever-agent": "0.6.1",
|
||||
"form-data": "2.3.1",
|
||||
"har-validator": "5.0.3",
|
||||
"hawk": "6.0.2",
|
||||
"http-signature": "1.2.0",
|
||||
"is-typedarray": "1.0.0",
|
||||
"isstream": "0.1.2",
|
||||
"json-stringify-safe": "5.0.1",
|
||||
"mime-types": "2.1.17",
|
||||
"oauth-sign": "0.8.2",
|
||||
"performance-now": "2.1.0",
|
||||
"qs": "6.5.1",
|
||||
"safe-buffer": "5.1.1",
|
||||
"stringstream": "0.0.5",
|
||||
"tough-cookie": "2.3.3",
|
||||
"tunnel-agent": "0.6.0",
|
||||
"uuid": "3.1.0"
|
||||
}
|
||||
},
|
||||
"ripemd160": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz",
|
||||
@@ -585,6 +1061,14 @@
|
||||
"safe-buffer": "5.1.1"
|
||||
}
|
||||
},
|
||||
"sntp": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz",
|
||||
"integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==",
|
||||
"requires": {
|
||||
"hoek": "4.2.0"
|
||||
}
|
||||
},
|
||||
"source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
@@ -603,6 +1087,34 @@
|
||||
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
|
||||
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
|
||||
},
|
||||
"sshpk": {
|
||||
"version": "1.13.1",
|
||||
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz",
|
||||
"integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=",
|
||||
"requires": {
|
||||
"asn1": "0.2.3",
|
||||
"assert-plus": "1.0.0",
|
||||
"bcrypt-pbkdf": "1.0.1",
|
||||
"dashdash": "1.14.1",
|
||||
"ecc-jsbn": "0.1.1",
|
||||
"getpass": "0.1.7",
|
||||
"jsbn": "0.1.1",
|
||||
"tweetnacl": "0.14.5"
|
||||
}
|
||||
},
|
||||
"stream-to": {
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/stream-to/-/stream-to-0.2.2.tgz",
|
||||
"integrity": "sha1-hDBgmNhf25kLn6MAsbPM9V6O8B0="
|
||||
},
|
||||
"stream-to-buffer": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/stream-to-buffer/-/stream-to-buffer-0.1.0.tgz",
|
||||
"integrity": "sha1-JnmdkDqyAlyb1VCsRxcbAPjdgKk=",
|
||||
"requires": {
|
||||
"stream-to": "0.2.2"
|
||||
}
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
|
||||
@@ -611,6 +1123,11 @@
|
||||
"safe-buffer": "5.1.1"
|
||||
}
|
||||
},
|
||||
"stringstream": {
|
||||
"version": "0.0.5",
|
||||
"resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz",
|
||||
"integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg="
|
||||
},
|
||||
"tar-stream": {
|
||||
"version": "1.5.5",
|
||||
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.5.5.tgz",
|
||||
@@ -622,6 +1139,45 @@
|
||||
"xtend": "4.0.1"
|
||||
}
|
||||
},
|
||||
"tinycolor2": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.1.tgz",
|
||||
"integrity": "sha1-9PrTM0R7wLB9TcjpIJ2POaisd+g="
|
||||
},
|
||||
"tough-cookie": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz",
|
||||
"integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=",
|
||||
"requires": {
|
||||
"punycode": "1.4.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"punycode": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
|
||||
"integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
|
||||
}
|
||||
}
|
||||
},
|
||||
"trim": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz",
|
||||
"integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0="
|
||||
},
|
||||
"tunnel-agent": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
|
||||
"integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
|
||||
"requires": {
|
||||
"safe-buffer": "5.1.1"
|
||||
}
|
||||
},
|
||||
"tweetnacl": {
|
||||
"version": "0.14.5",
|
||||
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
|
||||
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
|
||||
"optional": true
|
||||
},
|
||||
"universalify": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz",
|
||||
@@ -636,6 +1192,14 @@
|
||||
"querystring": "0.2.0"
|
||||
}
|
||||
},
|
||||
"url-regex": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/url-regex/-/url-regex-3.2.0.tgz",
|
||||
"integrity": "sha1-260eDJ4p4QXdCx8J9oYvf9tIJyQ=",
|
||||
"requires": {
|
||||
"ip-regex": "1.0.3"
|
||||
}
|
||||
},
|
||||
"util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
@@ -646,11 +1210,37 @@
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz",
|
||||
"integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g=="
|
||||
},
|
||||
"verror": {
|
||||
"version": "1.10.0",
|
||||
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
|
||||
"integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
|
||||
"requires": {
|
||||
"assert-plus": "1.0.0",
|
||||
"core-util-is": "1.0.2",
|
||||
"extsprintf": "1.3.0"
|
||||
}
|
||||
},
|
||||
"wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
|
||||
},
|
||||
"xhr": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/xhr/-/xhr-2.4.1.tgz",
|
||||
"integrity": "sha512-pAIU5vBr9Hiy5cpFIbPnwf0C18ZF86DBsZKrlsf87N5De/JbA6RJ83UP/cv+aljl4S40iRVMqP4pr4sF9Dnj0A==",
|
||||
"requires": {
|
||||
"global": "4.3.2",
|
||||
"is-function": "1.0.1",
|
||||
"parse-headers": "2.0.1",
|
||||
"xtend": "4.0.1"
|
||||
}
|
||||
},
|
||||
"xml-parse-from-string": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz",
|
||||
"integrity": "sha1-qQKekp09vN7RafPG4oI42VpdWig="
|
||||
},
|
||||
"xml2js": {
|
||||
"version": "0.4.17",
|
||||
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.17.tgz",
|
||||
|
@@ -11,14 +11,15 @@
|
||||
"archiver": "^2.1.1",
|
||||
"async": "^2.6.0",
|
||||
"aws-sdk": "^2.58.0",
|
||||
"dotenv": "^4.0.0",
|
||||
"electron-editor-context-menu": "^1.1.1",
|
||||
"electron-is": "^2.4.0",
|
||||
"electron-log": "^2.2.14",
|
||||
"electron-updater": "^2.18.2",
|
||||
"fs-extra": "^3.0.1",
|
||||
"jimp": "^0.2.28",
|
||||
"lodash.throttle": "^4.1.1",
|
||||
"minimist": "^1.2.0",
|
||||
"recursive-readdir": "^2.2.1",
|
||||
"dotenv": "^4.0.0"
|
||||
"recursive-readdir": "^2.2.1"
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user