Compare commits

...

35 Commits

Author SHA1 Message Date
Florian Rival
0e3f70627b Bump newIDE version 2018-02-03 19:32:52 +01:00
Florian Rival
a814a07105 Fix ResourcesEditor selection 2018-02-03 19:24:47 +01:00
Florian Rival
c49af90a9c Add program opening count to Keen.io analytics 2018-02-03 19:09:33 +01:00
Florian Rival
24afa155c8 Improve Keen.io analytics events by adding user profile information 2018-02-03 18:30:09 +01:00
Florian Rival
9e5a431516 Only run Fullstory on newIDE web-app 2018-02-03 17:53:57 +01:00
Florian Rival
182a94285c Unregister service worker (it is not ready yet) 2018-02-03 13:05:22 +01:00
Florian Rival
442c2c8dd9 Merge pull request #439 from 4ian/feature/resources-editor
Resources editor for newIDE
2018-02-03 12:57:22 +01:00
Florian Rival
f8fd0dd353 Add a preview in ResourcesEditor 2018-02-03 12:55:30 +01:00
Florian Rival
faad9e23ac Add ResourcesEditor with ResourcePropertiesEditor and Toolbar 2018-01-30 23:12:31 +01:00
Florian Rival
d2af0da1b1 Added tools method to ResourcesManager and finish working version of ResourcesList 2018-01-30 21:56:40 +01:00
Florian Rival
c65e5c3e49 [WIP] Add ResourcesEditor based on a generic SortableVirtualizedItemList
TODO:
* Use SortableVirtualizedItemList for ObjectsList and ObjectsGroupsList
* Add missing features (sorting, delete, thumbnail for images, properties edition) to ResourcesEditor
2018-01-30 00:58:21 +01:00
Florian Rival
24a8dfc5f0 Add SemiControlledTextField to be able to type freely in PropertiesEditor 2018-01-28 18:45:44 +01:00
Florian Rival
9c6790ac37 Update default gravity in PhysicsBehavior 2018-01-27 23:50:49 +01:00
Florian Rival
18ef7460ba Bump newIDE version 2018-01-27 19:34:36 +01:00
Florian Rival
63cd0e76c3 Fix warning 2018-01-27 19:34:27 +01:00
Florian Rival
bdbf7fd9fc Add support for editing BehaviorSharedData in newIDE
TODO:
* Support for cancelling modifications made on it in ScenePropertiesDialog
2018-01-27 19:13:27 +01:00
Florian Rival
6bbedbd8f9 Fix BehaviorSharedData not created by newIDE + fix warnings 2018-01-27 17:00:44 +01:00
Florian Rival
648bd1ff2e Show warning if game name or package name is empty when exporting in newIDE 2018-01-24 23:31:02 +01:00
Florian Rival
d4288caedb Fix .env file loading with electron-app and bump newIDE version 2018-01-23 00:15:13 +01:00
Florian Rival
0a35bc3272 Bump newIDE version 2018-01-22 23:35:55 +01:00
Florian Rival
d8b737a31f Fix LocalS3Export always reusing the same folder leading to useless files in exported game 2018-01-22 23:35:32 +01:00
Florian Rival
cfd2655f6c Bump newIDE version 2018-01-22 23:29:21 +01:00
Florian Rival
1896241b9d Move AWS S3 credentials to an .env file for games deployment on GDevelop hosting 2018-01-22 23:25:42 +01:00
Florian Rival
0ed22a6ee1 Fix upload to GDevelop hosting of exported games with large files 2018-01-22 22:52:44 +01:00
Florian Rival
2bfcb99c3e Add analytics when a signup is done 2018-01-22 00:20:32 +01:00
Florian Rival
815f8a520a Bump newIDE version 2018-01-21 22:11:59 +01:00
Florian Rival
f115b6607f Add PhysicsBehavior support to newIDE, with an example 2018-01-21 22:11:24 +01:00
Florian Rival
c876f67502 Add pathfinding example to newIDE web-app 2018-01-20 21:25:25 +01:00
Florian Rival
27674f272c Bump newIDE version 2018-01-20 19:21:13 +01:00
Florian Rival
02879507e3 Fix tests (outdated snapshots after adding Pathfinding to newIDE) 2018-01-20 19:19:38 +01:00
Florian Rival
0a7629878f Fix Sepia layer effect (broken since Pixi v4 update) 2018-01-20 19:00:22 +01:00
Florian Rival
b0368232d0 Add Parallax example to newIDE 2018-01-20 17:19:45 +01:00
Florian Rival
a32bf3db98 Add Pathfinding and Zombie Laser examples to newIDE 2018-01-20 17:02:47 +01:00
Florian Rival
64cbbb20d3 Expose PathfindingBehavior when building with Emscripten 2018-01-20 16:53:12 +01:00
Florian Rival
dd4fbecc98 Update some GDevelop services API to use api.gdevelop-app.com 2018-01-20 16:28:27 +01:00
138 changed files with 15301 additions and 1564 deletions

View File

@@ -13,6 +13,7 @@
"/usr/local/lib/wx/include/osx_cocoa-unicode-3.0",
"/usr/local/include/wx-3.0",
"/usr/include/machine",
"/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include",
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1",
"/usr/local/include",
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/8.0.0/include",
@@ -86,4 +87,4 @@
}
],
"version": 3
}
}

View File

@@ -67,7 +67,11 @@
"__functional_base": "cpp",
"__functional_base_03": "cpp",
"chrono": "cpp",
"ratio": "cpp"
"ratio": "cpp",
"atomic": "cpp",
"locale": "cpp",
"string_view": "cpp",
"__string": "cpp"
},
"files.exclude": {
"Binaries/*build*": true,

View File

@@ -945,7 +945,7 @@ void ResourcesEditor::Refresh()
gd::ResourceFolder & folder = project.GetResourcesManager().GetFolder(folders[i]);
wxTreeItemId folderItem = resourcesTree->AppendItem( resourcesTree->GetRootItem(), folders[i], -1, -1, new gd::TreeItemStringData("Folder", folders[i] ));
std::vector<gd::String> resources = folder.GetAllResourcesList();
std::vector<gd::String> resources = folder.GetAllResourceNames();
for (std::size_t j=0;j<resources.size();++j)
{
gd::Resource & resource = folder.GetResource(resources[j]);
@@ -959,7 +959,7 @@ void ResourcesEditor::Refresh()
//All images
allImagesItem = resourcesTree->AppendItem( resourcesTree->GetRootItem(), _("All images"), -1,-1, new gd::TreeItemStringData("BaseFolder", "" ));
std::vector<gd::String> resources = project.GetResourcesManager().GetAllResourcesList();
std::vector<gd::String> resources = project.GetResourcesManager().GetAllResourceNames();
for ( std::size_t i = 0;i <resources.size();i++ )
{
gd::Resource & resource = project.GetResourcesManager().GetResource(resources[i]);

View File

@@ -51,7 +51,7 @@ void ArbitraryResourceWorker::ExposeResources(gd::ResourcesManager * resourcesMa
resourcesManagers.push_back(resourcesManager);
std::vector<gd::String> resources = resourcesManager->GetAllResourcesList();
std::vector<gd::String> resources = resourcesManager->GetAllResourceNames();
for ( std::size_t i = 0;i < resources.size() ;i++ )
{
if ( resourcesManager->GetResource(resources[i]).UseFile() )

View File

@@ -45,7 +45,7 @@ std::vector<gd::String> ProjectResourcesAdder::GetAllUselessImages(gd::Project &
std::set<gd::String> & usedImages = inventorizer.GetAllUsedImages();
//Search all images resources not used
std::vector<gd::String> resources = project.GetResourcesManager().GetAllResourcesList();
std::vector<gd::String> resources = project.GetResourcesManager().GetAllResourceNames();
for (std::size_t i = 0;i < resources.size();i++)
{
if (project.GetResourcesManager().GetResource(resources[i]).GetKind() != "image")

View File

@@ -68,7 +68,7 @@ public:
* Usage example:
\code
std::map<gd::String, gd::PropertyDescriptor> properties;
properties[ToString(_("Initial speed"))].SetValue("5");
properties[_("Initial speed")].SetValue(gd::String::From(initialSpeed));
return properties;
\endcode

View File

@@ -5,6 +5,10 @@
*/
#include "GDCore/Project/BehaviorsSharedData.h"
#if defined(GD_IDE_ONLY)
#include <map>
#include "GDCore/IDE/Dialogs/PropertyDescriptor.h"
#endif
namespace gd
{
@@ -13,4 +17,12 @@ BehaviorsSharedData::~BehaviorsSharedData()
{
};
#if defined(GD_IDE_ONLY)
std::map<gd::String, gd::PropertyDescriptor> BehaviorsSharedData::GetProperties(gd::Project & project) const
{
std::map<gd::String, gd::PropertyDescriptor> nothing;
return nothing;
}
#endif
}

View File

@@ -8,9 +8,13 @@
#define BEHAVIORSSHAREDDATA_H
#include <memory>
#include <map>
#include "GDCore/String.h"
class BehaviorsRuntimeSharedData;
namespace gd { class SerializerElement; }
namespace gd { class PropertyDescriptor; }
namespace gd { class Project; }
namespace gd { class Layout; }
namespace gd
{
@@ -52,6 +56,31 @@ public:
virtual void SetTypeName(const gd::String & type_) { type = type_; };
#if defined(GD_IDE_ONLY)
/**
* \brief Called when the IDE wants to know about the properties of the shared data.
*
* Usage example:
\code
std::map<gd::String, gd::PropertyDescriptor> properties;
properties[_("Initial speed")].SetValue(gd::String::From(initialSpeed));
return properties;
\endcode
*
* \return a std::map with properties names as key.
* \see gd::PropertyDescriptor
*/
virtual std::map<gd::String, gd::PropertyDescriptor> GetProperties(gd::Project & project) const;
/**
* \brief Called when the IDE wants to update a property of the shared data
*
* \return false if the new value cannot be set
* \see gd::InitialInstance
*/
virtual bool UpdateProperty(const gd::String & name, const gd::String & value, gd::Project & project) {return false;};
/**
* \brief Serialize behaviors shared data.
*/

View File

@@ -141,7 +141,7 @@ void ImageManager::LoadPermanentImages()
//so as not to unload images that could be still present.
std::map < gd::String, std::shared_ptr<SFMLTextureWrapper> > newPermanentlyLoadedImages;
std::vector<gd::String> resources = resourcesManager->GetAllResourcesList();
std::vector<gd::String> resources = resourcesManager->GetAllResourceNames();
for ( std::size_t i = 0;i <resources.size();i++ )
{
try

View File

@@ -29,6 +29,7 @@ namespace gd
{
gd::Layer Layout::badLayer;
gd::BehaviorsSharedData Layout::badBehaviorSharedData;
Layout::Layout(const Layout & other)
{
@@ -74,6 +75,53 @@ void Layout::SetName(const gd::String & name_)
mangledName = gd::SceneNameMangler::GetMangledSceneName(name);
};
bool Layout::HasBehaviorSharedData(const gd::String & behaviorName)
{
return behaviorsInitialSharedDatas.find(behaviorName) != behaviorsInitialSharedDatas.end();
}
std::vector <gd::String> Layout::GetAllBehaviorSharedDataNames() const
{
std::vector < gd::String > allNames;
for (auto & it : behaviorsInitialSharedDatas)
allNames.push_back(it.first);
return allNames;
}
const gd::BehaviorsSharedData & Layout::GetBehaviorSharedData(const gd::String & behaviorName) const
{
auto it = behaviorsInitialSharedDatas.find(behaviorName);
if (it != behaviorsInitialSharedDatas.end())
return *it->second;
return badBehaviorSharedData;
}
gd::BehaviorsSharedData & Layout::GetBehaviorSharedData(const gd::String & behaviorName)
{
auto it = behaviorsInitialSharedDatas.find(behaviorName);
if (it != behaviorsInitialSharedDatas.end())
return *it->second;
return badBehaviorSharedData;
}
std::shared_ptr<gd::BehaviorsSharedData> Layout::GetBehaviorSharedDataSmartPtr(const gd::String & behaviorName)
{
auto it = behaviorsInitialSharedDatas.find(behaviorName);
if (it != behaviorsInitialSharedDatas.end())
return it->second;
return std::shared_ptr<gd::BehaviorsSharedData>();
}
const std::map < gd::String, std::shared_ptr<gd::BehaviorsSharedData> > & Layout::GetAllBehaviorSharedData() const
{
return behaviorsInitialSharedDatas;
}
gd::Layer & Layout::GetLayer(const gd::String & name)
{
std::vector<gd::Layer>::iterator layer = find_if(initialLayers.begin(), initialLayers.end(), bind2nd(gd::LayerHasName(), name));
@@ -83,6 +131,7 @@ gd::Layer & Layout::GetLayer(const gd::String & name)
return badLayer;
}
const gd::Layer & Layout::GetLayer(const gd::String & name) const
{
std::vector<gd::Layer>::const_iterator layer = find_if(initialLayers.begin(), initialLayers.end(), bind2nd(gd::LayerHasName(), name));
@@ -92,14 +141,17 @@ const gd::Layer & Layout::GetLayer(const gd::String & name) const
return badLayer;
}
gd::Layer & Layout::GetLayer(std::size_t index)
{
return initialLayers[index];
}
const gd::Layer & Layout::GetLayer (std::size_t index) const
{
return initialLayers[index];
}
std::size_t Layout::GetLayersCount() const
{
return initialLayers.size();

View File

@@ -172,37 +172,37 @@ public:
/** \name Layout layers management
* Members functions related to layout layers management.
* TODO: This should be moved to a separate class
* TODO: This could be moved to a separate class
*/
///@{
/**
* Must return true if the layer called "name" exists.
* \brief Return true if the layer called "name" exists.
*/
bool HasLayerNamed(const gd::String & name) const;
/**
* Must return a reference to the layer called "name".
* \brief Return a reference to the layer called "name".
*/
Layer & GetLayer(const gd::String & name);
/**
* Must return a reference to the layer called "name".
* \brief Return a reference to the layer called "name".
*/
const Layer & GetLayer(const gd::String & name) const;
/**
* Must return a reference to the layer at position "index" in the layers list
* \brief Return a reference to the layer at position "index" in the layers list
*/
Layer & GetLayer(std::size_t index);
/**
* Must return a reference to the layer at position "index" in the layers list
* \brief Return a reference to the layer at position "index" in the layers list
*/
const Layer & GetLayer (std::size_t index) const;
const Layer & GetLayer(std::size_t index) const;
/**
* Must return the position of the layer called "name" in the layers list
* \brief Return the position of the layer called "name" in the layers list
*/
std::size_t GetLayerPosition(const gd::String & name) const;
@@ -253,15 +253,45 @@ public:
///@}
/**
* Make sure that the scene had an instance of shared data for
* This ensures that the scene had an instance of shared data for
* every behavior of every object that can be used on the scene
* ( i.e. the objects of the scene and the global objects )
* (i.e. the objects of the scene and the global objects)
*
* Must be called when a behavior have been added/deleted
* or when a scene have been added to a project.
*/
void UpdateBehaviorsSharedData(gd::Project & project);
/**
* \brief Get the names of all shared data stored for behaviors
*/
std::vector <gd::String> GetAllBehaviorSharedDataNames() const;
/**
* \brief Check if shared data are stored for a behavior
*/
bool HasBehaviorSharedData(const gd::String & behaviorName);
/**
* \brief Get the shared data stored for a behavior
*/
const gd::BehaviorsSharedData & GetBehaviorSharedData(const gd::String & behaviorName) const;
/**
* \brief Get the shared data stored for a behavior
*/
gd::BehaviorsSharedData & GetBehaviorSharedData(const gd::String & behaviorName);
/**
* \brief Get a map of all shared data stored for behaviors
*/
const std::map < gd::String, std::shared_ptr<gd::BehaviorsSharedData> > & GetAllBehaviorSharedData() const;
/**
* \brief Get the (smart pointer to the) shared data stored for a behavior.
*/
std::shared_ptr<gd::BehaviorsSharedData> GetBehaviorSharedDataSmartPtr(const gd::String & behaviorName);
#if defined(GD_IDE_ONLY)
/**
* Return the settings associated to the layout.
@@ -357,9 +387,6 @@ public:
void UnserializeFrom(gd::Project & project, const SerializerElement & element);
///@}
//TODO: Send this to private part.
std::map < gd::String, std::shared_ptr<gd::BehaviorsSharedData> > behaviorsInitialSharedDatas; ///< Initial shared datas of behaviors
//TODO: GD C++ Platform specific code below
#if defined(GD_IDE_ONLY)
/** \name Events compilation and bitcode management
@@ -442,6 +469,7 @@ private:
gd::InitialInstancesContainer initialInstances; ///< Initial instances
std::vector < gd::Layer > initialLayers; ///< Initial layers
ObjectGroupsContainer objectGroups; ///< Objects groups
std::map < gd::String, std::shared_ptr<gd::BehaviorsSharedData> > behaviorsInitialSharedDatas; ///< Initial shared datas of behaviors
bool stopSoundsOnStartup; ///< True to make the scene stop all sounds at startup.
bool standardSortMethod; ///< True to sort objects using standard sort.
float oglFOV; ///< OpenGL Field Of View value
@@ -449,6 +477,7 @@ private:
float oglZFar; ///< OpenGL Far Z position
bool disableInputWhenNotFocused; /// If set to true, the input must be disabled when the window do not have the focus.
static gd::Layer badLayer; ///< Null object, returned when GetLayer can not find an appropriate layer.
static gd::BehaviorsSharedData badBehaviorSharedData; ///< Null object, returned when GetBehaviorSharedData can not find the specified behavior shared data.
#if defined(GD_IDE_ONLY)
EventsList events; ///< Scene events
gd::LayoutEditorCanvasOptions associatedSettings;

View File

@@ -105,7 +105,7 @@ bool ResourcesManager::HasResource(const gd::String & name) const
return false;
}
std::vector<gd::String> ResourcesManager::GetAllResourcesList()
std::vector<gd::String> ResourcesManager::GetAllResourceNames()
{
std::vector<gd::String> allResources;
for (std::size_t i = 0;i<resources.size();++i)
@@ -146,7 +146,7 @@ bool ResourcesManager::AddResource(const gd::String & name, const gd::String & f
return true;
}
std::vector<gd::String> ResourceFolder::GetAllResourcesList()
std::vector<gd::String> ResourceFolder::GetAllResourceNames()
{
std::vector<gd::String> allResources;
for (std::size_t i = 0;i<resources.size();++i)
@@ -351,6 +351,25 @@ bool ResourcesManager::MoveResourceDownInList(const gd::String & name)
return gd::MoveResourceDownInList(resources, name);
}
std::size_t ResourcesManager::GetResourcePosition(const gd::String & name) const
{
for (std::size_t i = 0;i<resources.size();++i)
{
if (resources[i]->GetName() == name) return i;
}
return gd::String::npos;
}
void ResourcesManager::MoveResource(std::size_t oldIndex, std::size_t newIndex)
{
if ( oldIndex >= resources.size() || newIndex >= resources.size() )
return;
auto resource = resources[oldIndex];
resources.erase(resources.begin() + oldIndex);
resources.insert(resources.begin() + newIndex, resource);
}
bool ResourcesManager::MoveFolderUpInList(const gd::String & name)
{
for (std::size_t i =1;i<folders.size();++i)

View File

@@ -293,9 +293,9 @@ public:
std::shared_ptr<Resource> CreateResource(const gd::String & kind);
/**
* \brief Get a list containing the name of all of the resources.
* \brief Get a list containing the names of all resources.
*/
std::vector<gd::String> GetAllResourcesList();
std::vector<gd::String> GetAllResourceNames();
#if defined(GD_IDE_ONLY)
/**
@@ -324,6 +324,11 @@ public:
*/
void RenameResource(const gd::String & oldName, const gd::String & newName);
/**
* \brief Return the position of the layer called "name" in the layers list
*/
std::size_t GetResourcePosition(const gd::String & name) const;
/**
* \brief Move a resource up in the list
*/
@@ -334,6 +339,11 @@ public:
*/
bool MoveResourceDownInList(const gd::String & name);
/**
* Change the position of the specified resource.
*/
void MoveResource(std::size_t oldIndex, std::size_t newIndex);
/**
* \brief Return true if the folder exists.
*/
@@ -445,7 +455,7 @@ public:
/**
* Get a list containing the name of all of the resources.
*/
virtual std::vector<gd::String> GetAllResourcesList();
virtual std::vector<gd::String> GetAllResourceNames();
/**
* Move a resource up in the list

View File

@@ -84,7 +84,7 @@ TEST_CASE( "Resources", "[common][resources]" ) {
gd::ProjectResourcesAdder::RemoveAllUselessImages(project);
std::vector<gd::String> remainingResources =
project.GetResourcesManager().GetAllResourcesList();
project.GetResourcesManager().GetAllResourceNames();
REQUIRE(remainingResources.size() == 2);
REQUIRE(remainingResources[0] == "res1");
REQUIRE(remainingResources[1] == "res4");

View File

@@ -21,7 +21,7 @@ class GD_EXTENSION_API AdMobObject : public gd::Object
public:
AdMobObject(gd::String name_);
virtual ~AdMobObject() {};
virtual std::unique_ptr<gd::Object> Clone() const { return gd::make_unique<AdMobObject>(*this); }
virtual std::unique_ptr<gd::Object> Clone() const override { return gd::make_unique<AdMobObject>(*this); }
#if !defined(GD_NO_WX_GUI)
void DrawInitialInstance(gd::InitialInstance & instance, sf::RenderTarget & renderTarget, gd::Project & project, gd::Layout & layout) override;

View File

@@ -10,7 +10,7 @@ include(CMakeUtils.txt) #Functions to factor common tasks done in CMakeLists.txt
#Add all the CMakeLists:
ADD_SUBDIRECTORY(AdMobObject)
ADD_SUBDIRECTORY(AnchorBehavior)
IF (NOT EMSCRIPTEN) #Only add some extensions when compiling with emscripten.
IF (NOT EMSCRIPTEN)
ADD_SUBDIRECTORY(AdvancedXML)
ADD_SUBDIRECTORY(AES)
ADD_SUBDIRECTORY(Box3DObject)
@@ -35,9 +35,9 @@ ENDIF()
ADD_SUBDIRECTORY(PanelSpriteObject)
IF (NOT EMSCRIPTEN)
ADD_SUBDIRECTORY(PathBehavior)
ADD_SUBDIRECTORY(PathfindingBehavior)
ADD_SUBDIRECTORY(PhysicsBehavior)
ENDIF()
ADD_SUBDIRECTORY(PathfindingBehavior)
ADD_SUBDIRECTORY(PhysicsBehavior)
ADD_SUBDIRECTORY(PlatformBehavior)
ADD_SUBDIRECTORY(PrimitiveDrawing)
ADD_SUBDIRECTORY(Shopify)

View File

@@ -7,8 +7,6 @@ This project is released under the MIT License.
#if defined(GD_IDE_ONLY)
#include "GDCore/Extensions/PlatformExtension.h"
#include "GDCore/Tools/Localization.h"
#include <iostream>
void DeclarePanelSpriteObjectExtension(gd::PlatformExtension & extension);

View File

@@ -322,13 +322,13 @@ PathBehaviorEditor::PathBehaviorEditor(wxWindow* parent, gd::Project & game_, gd
followAngleCheck->SetValue(behavior.FollowAngle());
//Setup shared datas
if ( !scene || scene->behaviorsInitialSharedDatas.find(behavior.GetName()) == scene->behaviorsInitialSharedDatas.end())
if (!scene || !scene->HasBehaviorSharedData(behavior.GetName()))
{
gd::LogError(_("Unable to access to shared datas."));
return;
}
sharedDatas = std::dynamic_pointer_cast<ScenePathDatas>(scene->behaviorsInitialSharedDatas[behavior.GetName()]);
sharedDatas = std::dynamic_pointer_cast<ScenePathDatas>(scene->GetBehaviorSharedDataSmartPtr(behavior.GetName()));
if ( sharedDatas == std::shared_ptr<ScenePathDatas>() )
{

File diff suppressed because it is too large Load Diff

View File

@@ -8,26 +8,21 @@ This project is released under the MIT License.
#include "GDCore/Extensions/PlatformExtension.h"
#include "GDCore/Tools/Localization.h"
#include <iostream>
void DeclarePathfindingBehaviorExtension(gd::PlatformExtension & extension);
/**
* \brief This class declares information about the JS extension.
*/
class JsExtension : public gd::PlatformExtension
class PathfindingBehaviorJsExtension : public gd::PlatformExtension
{
public:
/**
* \brief Constructor of an extension declares everything the extension contains: objects, actions, conditions and expressions.
*/
JsExtension()
PathfindingBehaviorJsExtension()
{
SetExtensionInformation("PathfindingBehavior",
_("Pathfinding behavior"),
_("Compute paths for objects avoiding obstacles."),
"Florian Rival",
"Open source (MIT License)");
CloneExtension("GDevelop C++ platform", "PathfindingBehavior");
DeclarePathfindingBehaviorExtension(*this);
GetBehaviorMetadata("PathfindingBehavior::PathfindingBehavior")
.SetIncludeFile("Extensions/PathfindingBehavior/pathfindingruntimebehavior.js")
@@ -103,14 +98,21 @@ public:
}
StripUnimplementedInstructionsAndExpressions();
GD_COMPLETE_EXTENSION_COMPILATION_INFORMATION();
};
};
#if defined(EMSCRIPTEN)
extern "C" gd::PlatformExtension * CreateGDJSPathfindingBehaviorExtension() {
return new PathfindingBehaviorJsExtension;
}
#else
/**
* Used by GDevelop to create the extension class
* -- Do not need to be modified. --
*/
extern "C" gd::PlatformExtension * GD_EXTENSION_API CreateGDJSExtension() {
return new JsExtension;
return new PathfindingBehaviorJsExtension;
}
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -6,29 +6,23 @@ This project is released under the MIT License.
*/
#if defined(GD_IDE_ONLY)
#include "GDCore/Extensions/PlatformExtension.h"
#include <iostream>
#include "GDCore/Tools/Localization.h"
void DeclarePhysicsBehaviorExtension(gd::PlatformExtension & extension);
/**
* \brief This class declares information about the JS extension.
*/
class JsExtension : public gd::PlatformExtension
class PhysicsBehaviorJsExtension : public gd::PlatformExtension
{
public:
/**
* \brief Constructor of an extension declares everything the extension contains: objects, actions, conditions and expressions.
*/
JsExtension()
PhysicsBehaviorJsExtension()
{
SetExtensionInformation("PhysicsBehavior",
_("Physics behavior"),
_("Behavior allowing to move objects as if they were subject to the laws of physics."),
"Florian Rival",
"Open source (MIT License)");
CloneExtension("GDevelop C++ platform", "PhysicsBehavior");
DeclarePhysicsBehaviorExtension(*this);
GetBehaviorMetadata("PhysicsBehavior::PhysicsBehavior")
.SetIncludeFile("Extensions/PhysicsBehavior/box2djs/box2d.js")
@@ -145,14 +139,21 @@ public:
*/
StripUnimplementedInstructionsAndExpressions();
GD_COMPLETE_EXTENSION_COMPILATION_INFORMATION();
};
};
#if defined(EMSCRIPTEN)
extern "C" gd::PlatformExtension * CreateGDJSPhysicsBehaviorExtension() {
return new PhysicsBehaviorJsExtension;
}
#else
/**
* Used by GDevelop to create the extension class
* -- Do not need to be modified. --
*/
extern "C" gd::PlatformExtension * GD_EXTENSION_API CreateGDJSExtension() {
return new JsExtension;
return new PhysicsBehaviorJsExtension;
}
#endif
#endif

View File

@@ -7,6 +7,7 @@ This project is released under the MIT License.
#include "PhysicsBehavior.h"
#include <string>
#include "GDCore/Tools/Localization.h"
#include "Box2D/Box2D.h"
#include "Triangulation/triangulate.h"
#include "GDCpp/Runtime/RuntimeScene.h"
@@ -17,6 +18,10 @@ This project is released under the MIT License.
#include "GDCpp/Runtime/Project/Project.h"
#include "GDCpp/Runtime/Project/Layout.h"
#include "RuntimeScenePhysicsDatas.h"
#if defined(GD_IDE_ONLY)
#include <map>
#include "GDCore/IDE/Dialogs/PropertyDescriptor.h"
#endif
#undef GetObject
@@ -100,10 +105,6 @@ void PhysicsBehavior::DoStepPostEvents(RuntimeScene & scene)
float newHeight = object->GetHeight();
if ( (int)objectOldWidth != (int)newWidth || (int)objectOldHeight != (int)newHeight )
{
/*std::cout << "Changed:" << (int)objectOldWidth << "!=" << (int)newWidth << std::endl;
std::cout << "Changed:" << (int)objectOldHeight << "!=" << (int)newHeight << std::endl;
std::cout << "( Object name:" << object->GetName() << std::endl;*/
double oldAngularVelocity = body->GetAngularVelocity();
b2Vec2 oldVelocity = body->GetLinearVelocity();
@@ -700,6 +701,76 @@ void PhysicsBehavior::UnserializeFrom(const gd::SerializerElement & element)
SetPolygonCoords(PhysicsBehavior::GetCoordsVectorFromString(coordsStr, '/', ';'));
}
#if defined(GD_IDE_ONLY)
std::map<gd::String, gd::PropertyDescriptor> PhysicsBehavior::GetProperties(gd::Project & project) const
{
std::map<gd::String, gd::PropertyDescriptor> properties;
gd::String shapeTypeStr = _("Box (rectangle)");
if (shapeType == Box) shapeTypeStr = _("Box (rectangle)");
else if (shapeType == Circle) shapeTypeStr = _("Circle");
else if (shapeType == CustomPolygon) shapeTypeStr = _("Custom polygon");
properties[_("Shape")]
.SetValue(shapeTypeStr)
.SetType("Choice")
.AddExtraInfo(_("Box (rectangle)"))
.AddExtraInfo(_("Circle"));
properties[_("Dynamic object")].SetValue(dynamic ? "true" : "false").SetType("Boolean");
properties[_("Fixed rotation")].SetValue(fixedRotation ? "true" : "false").SetType("Boolean");
properties[_("Consider as bullet (better collision handling)")].SetValue(isBullet ? "true" : "false").SetType("Boolean");
properties[_("Mass density")].SetValue(gd::String::From(massDensity));
properties[_("Friction")].SetValue(gd::String::From(averageFriction));
properties[_("Restitution (elasticity)")].SetValue(gd::String::From(averageRestitution));
properties[_("Linear Damping")].SetValue(gd::String::From(linearDamping));
properties[_("Angular Damping")].SetValue(gd::String::From(angularDamping));
properties[_("PLEASE_ALSO_SHOW_EDIT_BUTTON_THANKS")].SetValue("");
return properties;
}
bool PhysicsBehavior::UpdateProperty(const gd::String & name, const gd::String & value, gd::Project & project)
{
if (name == _("Shape"))
{
if (value == _("Box (rectangle)"))
shapeType = Box;
else if (value == _("Circle"))
shapeType = Circle;
else if (value == _("Custom polygon"))
shapeType = CustomPolygon;
}
if ( name == _("Dynamic object") ) {
dynamic = (value != "0");
}
if ( name == _("Fixed rotation") ) {
fixedRotation = (value != "0");
}
if ( name == _("Consider as bullet (better collision handling)") ) {
isBullet = (value != "0");
}
if ( name == _("Mass density") ) {
massDensity = value.To<float>();
}
if ( name == _("Friction") ) {
averageFriction = value.To<float>();
}
if ( name == _("Restitution (elasticity)") ) {
averageRestitution = value.To<float>();
}
if ( name == _("Linear Damping") ) {
if ( value.To<float>() < 0 ) return false;
linearDamping = value.To<float>();
}
if ( name == _("Angular Damping") ) {
if ( value.To<float>() < 0 ) return false;
angularDamping = value.To<float>();
}
return true;
}
#endif
gd::String PhysicsBehavior::GetStringFromCoordsVector(const std::vector<sf::Vector2f> &vec, char32_t coordsSep, char32_t composantSep)
{

View File

@@ -56,6 +56,9 @@ public:
* Called when user wants to edit the behavior.
*/
virtual void EditBehavior( wxWindow* parent, gd::Project & project_, gd::Layout * layout_, gd::MainFrameWrapper & mainFrameWrapper_ );
virtual std::map<gd::String, gd::PropertyDescriptor> GetProperties(gd::Project & project) const;
virtual bool UpdateProperty(const gd::String & name, const gd::String & value, gd::Project & project);
#endif
/**

View File

@@ -241,13 +241,13 @@ scene(scene_)
}
//Setup shared datas
if ( !scene || scene->behaviorsInitialSharedDatas.find(behavior.GetName()) == scene->behaviorsInitialSharedDatas.end())
if (!scene || !scene->HasBehaviorSharedData(behavior.GetName()))
{
gd::LogError(_("Unable to access to shared datas."));
return;
}
sharedDatas = std::dynamic_pointer_cast<ScenePhysicsDatas>(scene->behaviorsInitialSharedDatas[behavior.GetName()]);
sharedDatas = std::dynamic_pointer_cast<ScenePhysicsDatas>(scene->GetBehaviorSharedDataSmartPtr(behavior.GetName()));
if ( sharedDatas == std::shared_ptr<ScenePhysicsDatas>() )
{

View File

@@ -6,9 +6,46 @@ This project is released under the MIT License.
*/
#include "ScenePhysicsDatas.h"
#include "GDCore/Tools/Localization.h"
#include "GDCore/Serialization/SerializerElement.h"
#if defined(GD_IDE_ONLY)
#include <map>
#include "GDCore/String.h"
#include "GDCore/CommonTools.h"
#include "GDCore/Project/Project.h"
#include "GDCore/IDE/Dialogs/PropertyDescriptor.h"
#endif
#if defined(GD_IDE_ONLY)
std::map<gd::String, gd::PropertyDescriptor> ScenePhysicsDatas::GetProperties(gd::Project & project) const
{
std::map<gd::String, gd::PropertyDescriptor> properties;
properties[_("Gravity on X axis (in m/s²)")].SetValue(gd::String::From(gravityX));
properties[_("Gravity on Y axis (in m/s²)")].SetValue(gd::String::From(gravityY));
properties[_("X Scale: number of pixels for 1 meter")].SetValue(gd::String::From(scaleX));
properties[_("Y Scale: number of pixels for 1 meter")].SetValue(gd::String::From(scaleY));
return properties;
}
bool ScenePhysicsDatas::UpdateProperty(const gd::String & name, const gd::String & value, gd::Project & project)
{
if (name == _("Gravity on X axis (in m/s²)")) {
gravityX = value.To<float>();
}
if (name == _("Gravity on Y axis (in m/s²)")) {
gravityY = value.To<float>();
}
if (name == _("X scale: number of pixels for 1 meter")) {
scaleX = value.To<float>();
}
if (name == _("Y scale: number of pixels for 1 meter")) {
scaleY = value.To<float>();
}
return true;
}
void ScenePhysicsDatas::SerializeTo(gd::SerializerElement & element) const
{
element.SetAttribute("gravityX", gravityX);

View File

@@ -17,7 +17,7 @@ This project is released under the MIT License.
class ScenePhysicsDatas : public gd::BehaviorsSharedData
{
public:
ScenePhysicsDatas() : BehaviorsSharedData(), gravityX(0), gravityY(0), scaleX(100), scaleY(100)
ScenePhysicsDatas() : BehaviorsSharedData(), gravityX(0), gravityY(9), scaleX(100), scaleY(100)
{
};
virtual ~ScenePhysicsDatas() {};
@@ -34,6 +34,8 @@ public:
}
#if defined(GD_IDE_ONLY)
virtual std::map<gd::String, gd::PropertyDescriptor> GetProperties(gd::Project & project) const;
virtual bool UpdateProperty(const gd::String & name, const gd::String & value, gd::Project & project);
virtual void SerializeTo(gd::SerializerElement & element) const;
#endif

View File

@@ -450,7 +450,7 @@ bool RuntimeScene::LoadFromSceneAndCustomInstances( const gd::Layout & scene, co
//Behaviors shared data
std::cout << ".";
behaviorsSharedDatas.LoadFrom(scene.behaviorsInitialSharedDatas);
behaviorsSharedDatas.LoadFrom(scene.GetAllBehaviorSharedData());
std::cout << ".";
//Extensions specific initialization

View File

@@ -137,6 +137,8 @@ gd::PlatformExtension * CreateGDJSInventoryExtension();
gd::PlatformExtension * CreateGDJSLinkedObjectsExtension();
gd::PlatformExtension * CreateGDJSSystemInfoExtension();
gd::PlatformExtension * CreateGDJSShopifyExtension();
gd::PlatformExtension * CreateGDJSPathfindingBehaviorExtension();
gd::PlatformExtension * CreateGDJSPhysicsBehaviorExtension();
}
#endif
@@ -183,6 +185,8 @@ JsPlatform::JsPlatform() :
AddExtension(std::shared_ptr<gd::PlatformExtension>(CreateGDJSLinkedObjectsExtension())); std::cout.flush();
AddExtension(std::shared_ptr<gd::PlatformExtension>(CreateGDJSSystemInfoExtension())); std::cout.flush();
AddExtension(std::shared_ptr<gd::PlatformExtension>(CreateGDJSShopifyExtension())); std::cout.flush();
AddExtension(std::shared_ptr<gd::PlatformExtension>(CreateGDJSPathfindingBehaviorExtension())); std::cout.flush();
AddExtension(std::shared_ptr<gd::PlatformExtension>(CreateGDJSPhysicsBehaviorExtension())); std::cout.flush();
#endif
std::cout << "done." << std::endl;
};

View File

@@ -1,6 +1,7 @@
gdjs.LayerPixiRenderer = function(layer, runtimeSceneRenderer)
{
this._pixiContainer = new PIXI.Container();
this._filters = {};
this._layer = layer;
runtimeSceneRenderer.getPIXIContainer().addChild(this._pixiContainer);

View File

@@ -86,12 +86,14 @@ gdjs.PixiFiltersTools._filters = {
},
Sepia: {
makeFilter: function() {
return new PIXI.filters.SepiaFilter();
var colorMatrix = new PIXI.filters.ColorMatrixFilter();
colorMatrix.sepia();
return colorMatrix;
},
updateParameter: function(filter, parameterName, value) {
if (parameterName !== 'opacity') return;
filter.sepia = value;
filter.alpha = value;
},
},
};

View File

@@ -1,4 +1,4 @@
# Rename this file as .env.local and complete the following values.
# Copy this file as ".env.local" and complete the following values.
# If values are not completed, some features will be unavailable.
REACT_APP_PREVIEW_S3_ACCESS_KEY_ID=

View File

@@ -13,6 +13,7 @@ declare type gdExternalEvents = EmscriptenObject;
declare type gdSerializerElement = EmscriptenObject;
declare type gdInitialInstance = EmscriptenObject;
declare type gdBaseEvent = EmscriptenObject;
declare type gdResource = EmscriptenObject;
//Represents all objects that have serializeTo and unserializeFrom methods.
declare type gdSerializable = EmscriptenObject;

View File

@@ -25,27 +25,8 @@
<meta name="theme-color" content="#4ab0e4">
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
<!-- Fullstory user analytics -->
<script>
window['_fs_debug'] = false;
window['_fs_host'] = 'fullstory.com';
window['_fs_org'] = '8DWZ1';
window['_fs_namespace'] = 'FS';
(function(m,n,e,t,l,o,g,y){
if (e in m) {if(m.console && m.console.log) { m.console.log('FullStory namespace conflict. Please set window["_fs_namespace"].');} return;}
g=m[e]=function(a,b){g.q?g.q.push([a,b]):g._api(a,b);};g.q=[];
o=n.createElement(t);o.async=1;o.src='https://'+_fs_host+'/s/fs.js';
y=n.getElementsByTagName(t)[0];y.parentNode.insertBefore(o,y);
g.identify=function(i,v){g(l,{uid:i});if(v)g(l,v)};g.setUserVars=function(v){g(l,v)};
g.identifyAccount=function(i,v){o='account';v=v||{};v.acctId=i;g(o,v)};
g.clearUserCookie=function(c,d,i){if(!c || document.cookie.match('fs_uid=[`;`]*`[`;`]*`[`;`]*`')){
d=n.domain;while(1){n.cookie='fs_uid=;domain='+d+
';path=/;expires='+new Date(0).toUTCString();i=d.indexOf('.');if(i<0)break;d=d.slice(i+1)}}};
})(window,document,window['_fs_namespace'],'script','user');
</script>
<!-- Stripe.com Checkout -->
<script src="https://checkout.stripe.com/checkout.js"></script>
<!-- Stripe.com Checkout -->
<script src="https://checkout.stripe.com/checkout.js"></script>
</head>
<body>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -0,0 +1,760 @@
{
"firstLayout": "",
"gdVersion": {
"build": 96,
"major": 4,
"minor": 0,
"revision": 0
},
"properties": {
"folderProject": false,
"linuxExecutableFilename": "",
"macExecutableFilename": "",
"packageName": "",
"projectFile": "/Users/florian/Desktop/parallax/parallax.json",
"useExternalSourceFiles": false,
"winExecutableFilename": "",
"winExecutableIconFile": "",
"name": "Project",
"author": "",
"windowWidth": 600,
"windowHeight": 400,
"latestCompilationDirectory": "",
"maxFPS": 60,
"minFPS": 10,
"verticalSync": false,
"extensions": [
{
"name": "BuiltinObject"
},
{
"name": "BuiltinAudio"
},
{
"name": "BuiltinVariables"
},
{
"name": "BuiltinTime"
},
{
"name": "BuiltinMouse"
},
{
"name": "BuiltinKeyboard"
},
{
"name": "BuiltinJoystick"
},
{
"name": "BuiltinCamera"
},
{
"name": "BuiltinWindow"
},
{
"name": "BuiltinFile"
},
{
"name": "BuiltinNetwork"
},
{
"name": "BuiltinScene"
},
{
"name": "BuiltinAdvanced"
},
{
"name": "Sprite"
},
{
"name": "BuiltinCommonInstructions"
},
{
"name": "BuiltinCommonConversions"
},
{
"name": "BuiltinStringInstructions"
},
{
"name": "BuiltinMathematicalTools"
},
{
"name": "BuiltinExternalLayouts"
}
],
"platforms": [
{
"name": "GDevelop JS platform"
}
],
"currentPlatform": "GDevelop JS platform"
},
"resources": {
"resources": [
{
"alwaysLoaded": false,
"file": "Vegetation_(middle_layer).png",
"kind": "image",
"name": "Vegetation_(middle_layer).png",
"smoothed": true,
"userAdded": true
},
{
"alwaysLoaded": false,
"file": "Ground_(front_layer).png",
"kind": "image",
"name": "Ground_(front_layer).png",
"smoothed": true,
"userAdded": true
},
{
"alwaysLoaded": false,
"file": "Sky_back_layer.png",
"kind": "image",
"name": "Sky_back_layer.png",
"smoothed": true,
"userAdded": true
},
{
"alwaysLoaded": false,
"file": "Elisa_standing.png",
"kind": "image",
"name": "Elisa_standing.png",
"smoothed": true,
"userAdded": true
}
],
"resourceFolders": []
},
"objects": [],
"objectsGroups": [],
"variables": [],
"layouts": [
{
"b": 209,
"disableInputWhenNotFocused": true,
"mangledName": "New_32scene",
"name": "New scene",
"oglFOV": 90,
"oglZFar": 500,
"oglZNear": 1,
"r": 209,
"standardSortMethod": true,
"stopSoundsOnStartup": true,
"title": "",
"v": 209,
"uiSettings": {
"grid": true,
"gridB": 255,
"gridG": 180,
"gridHeight": 32,
"gridOffsetX": 0,
"gridOffsetY": 0,
"gridR": 158,
"gridWidth": 32,
"snap": true,
"windowMask": false,
"zoomFactor": 1
},
"objectsGroups": [],
"variables": [],
"instances": [
{
"angle": 0,
"customSize": false,
"height": 0,
"layer": "",
"locked": false,
"name": "ObjectToFollow",
"width": 0,
"x": -128,
"y": 320,
"zOrder": 1,
"numberProperties": [],
"stringProperties": [],
"initialVariables": []
},
{
"angle": 0,
"customSize": false,
"height": 0,
"layer": "Layer4",
"locked": false,
"name": "Background",
"width": 0,
"x": -640,
"y": -32,
"zOrder": 1,
"numberProperties": [],
"stringProperties": [],
"initialVariables": []
},
{
"angle": 0,
"customSize": false,
"height": 0,
"layer": "Layer3",
"locked": false,
"name": "Background",
"width": 0,
"x": -640,
"y": -32,
"zOrder": 1,
"numberProperties": [
{
"name": "animation",
"value": 1
}
],
"stringProperties": [],
"initialVariables": []
},
{
"angle": 0,
"customSize": false,
"height": 0,
"layer": "Layer2",
"locked": false,
"name": "Background",
"width": 0,
"x": -608,
"y": -32,
"zOrder": 1,
"numberProperties": [
{
"name": "animation",
"value": 2
}
],
"stringProperties": [],
"initialVariables": []
},
{
"angle": 0,
"customSize": false,
"height": 0,
"layer": "Layer3",
"locked": false,
"name": "Background",
"width": 0,
"x": 0,
"y": -32,
"zOrder": 1,
"numberProperties": [
{
"name": "animation",
"value": 1
}
],
"stringProperties": [],
"initialVariables": []
},
{
"angle": 0,
"customSize": false,
"height": 0,
"layer": "Layer2",
"locked": false,
"name": "Background",
"width": 0,
"x": 0,
"y": -32,
"zOrder": 1,
"numberProperties": [
{
"name": "animation",
"value": 2
}
],
"stringProperties": [],
"initialVariables": []
},
{
"angle": 0,
"customSize": false,
"height": 0,
"layer": "Layer4",
"locked": false,
"name": "Background",
"width": 0,
"x": 0,
"y": -32,
"zOrder": 1,
"numberProperties": [],
"stringProperties": [],
"initialVariables": []
}
],
"objects": [
{
"name": "Background",
"type": "Sprite",
"updateIfNotVisible": true,
"variables": [],
"behaviors": [],
"animations": [
{
"name": "",
"useMultipleDirections": false,
"directions": [
{
"looping": false,
"timeBetweenFrames": 1,
"sprites": [
{
"hasCustomCollisionMask": false,
"image": "Sky_back_layer.png",
"points": [],
"originPoint": {
"name": "origine",
"x": 0,
"y": 0
},
"centerPoint": {
"automatic": true,
"name": "centre",
"x": 0,
"y": 0
},
"customCollisionMask": [
[
{
"x": 0,
"y": 0
},
{
"x": 0,
"y": 0
},
{
"x": 0,
"y": 0
},
{
"x": 0,
"y": 0
}
]
]
}
]
}
]
},
{
"name": "",
"useMultipleDirections": false,
"directions": [
{
"looping": false,
"timeBetweenFrames": 1,
"sprites": [
{
"hasCustomCollisionMask": false,
"image": "Vegetation_(middle_layer).png",
"points": [],
"originPoint": {
"name": "origine",
"x": 0,
"y": 0
},
"centerPoint": {
"automatic": true,
"name": "centre",
"x": 0,
"y": 0
},
"customCollisionMask": [
[
{
"x": 0,
"y": 0
},
{
"x": 0,
"y": 0
},
{
"x": 0,
"y": 0
},
{
"x": 0,
"y": 0
}
]
]
}
]
}
]
},
{
"name": "",
"useMultipleDirections": false,
"directions": [
{
"looping": false,
"timeBetweenFrames": 1,
"sprites": [
{
"hasCustomCollisionMask": false,
"image": "Ground_(front_layer).png",
"points": [],
"originPoint": {
"name": "origine",
"x": 0,
"y": 0
},
"centerPoint": {
"automatic": true,
"name": "centre",
"x": 0,
"y": 0
},
"customCollisionMask": [
[
{
"x": 0,
"y": 0
},
{
"x": 0,
"y": 0
},
{
"x": 0,
"y": 0
},
{
"x": 0,
"y": 0
}
]
]
}
]
}
]
}
]
},
{
"name": "ObjectToFollow",
"type": "Sprite",
"updateIfNotVisible": true,
"variables": [],
"behaviors": [],
"animations": [
{
"name": "",
"useMultipleDirections": false,
"directions": [
{
"looping": false,
"timeBetweenFrames": 1,
"sprites": [
{
"hasCustomCollisionMask": false,
"image": "Elisa_standing.png",
"points": [],
"originPoint": {
"name": "origine",
"x": 0,
"y": 0
},
"centerPoint": {
"automatic": true,
"name": "centre",
"x": 0,
"y": 0
},
"customCollisionMask": [
[
{
"x": 0,
"y": 0
},
{
"x": 0,
"y": 0
},
{
"x": 0,
"y": 0
},
{
"x": 0,
"y": 0
}
]
]
}
]
}
]
}
]
}
],
"events": [
{
"disabled": false,
"folded": false,
"type": "BuiltinCommonInstructions::Comment",
"color": {
"b": 109,
"g": 230,
"r": 255,
"textB": 0,
"textG": 0,
"textR": 0
},
"comment": "The character can just be moved left and right - in a real game you can use the Platformer character behavior.",
"comment2": ""
},
{
"disabled": false,
"folded": false,
"type": "BuiltinCommonInstructions::Standard",
"conditions": [
{
"type": {
"inverted": false,
"value": "KeyPressed"
},
"parameters": [
"",
"Left"
],
"subInstructions": []
}
],
"actions": [
{
"type": {
"inverted": false,
"value": "AddForceXY"
},
"parameters": [
"ObjectToFollow",
"-200",
"0",
"0"
],
"subInstructions": []
}
],
"events": []
},
{
"disabled": false,
"folded": false,
"type": "BuiltinCommonInstructions::Standard",
"conditions": [
{
"type": {
"inverted": false,
"value": "KeyPressed"
},
"parameters": [
"",
"Right"
],
"subInstructions": []
}
],
"actions": [
{
"type": {
"inverted": false,
"value": "AddForceXY"
},
"parameters": [
"ObjectToFollow",
"200",
"0",
"0"
],
"subInstructions": []
}
],
"events": []
},
{
"disabled": false,
"folded": false,
"type": "BuiltinCommonInstructions::Standard",
"conditions": [],
"actions": [
{
"type": {
"inverted": false,
"value": "MoveObjects"
},
"parameters": [
""
],
"subInstructions": []
}
],
"events": []
},
{
"disabled": false,
"folded": false,
"type": "BuiltinCommonInstructions::Comment",
"color": {
"b": 109,
"g": 230,
"r": 255,
"textB": 0,
"textG": 0,
"textR": 0
},
"comment": "Parallax is achieved by setting the position of the camera to the position of the player, multiplied by a factor (between 0 and 1).\nA small factor makes the layer appears far.\nA factor close to 1 makes the layer appears like if it was near the player.",
"comment2": ""
},
{
"disabled": false,
"folded": false,
"type": "BuiltinCommonInstructions::Standard",
"conditions": [],
"actions": [
{
"type": {
"inverted": false,
"value": "CameraX"
},
"parameters": [
"",
"=",
"ObjectToFollow.X()",
"",
""
],
"subInstructions": []
},
{
"type": {
"inverted": false,
"value": "CameraX"
},
"parameters": [
"",
"=",
"ObjectToFollow.X()*0.75",
"\"Layer2\"",
""
],
"subInstructions": []
},
{
"type": {
"inverted": false,
"value": "CameraX"
},
"parameters": [
"",
"=",
"ObjectToFollow.X()*0.50",
"\"Layer3\"",
""
],
"subInstructions": []
},
{
"type": {
"inverted": false,
"value": "CameraX"
},
"parameters": [
"",
"=",
"ObjectToFollow.X()*0.25",
"\"Layer4\"",
""
],
"subInstructions": []
}
],
"events": []
}
],
"layers": [
{
"name": "Layer4",
"visibility": true,
"cameras": [
{
"defaultSize": true,
"defaultViewport": true,
"height": 0,
"viewportBottom": 1,
"viewportLeft": 0,
"viewportRight": 1,
"viewportTop": 0,
"width": 0
}
],
"effects": []
},
{
"name": "Layer3",
"visibility": true,
"cameras": [
{
"defaultSize": true,
"defaultViewport": true,
"height": 0,
"viewportBottom": 1,
"viewportLeft": 0,
"viewportRight": 1,
"viewportTop": 0,
"width": 0
}
],
"effects": []
},
{
"name": "Layer2",
"visibility": true,
"cameras": [
{
"defaultSize": true,
"defaultViewport": true,
"height": 0,
"viewportBottom": 1,
"viewportLeft": 0,
"viewportRight": 1,
"viewportTop": 0,
"width": 0
}
],
"effects": []
},
{
"name": "",
"visibility": true,
"cameras": [
{
"defaultSize": true,
"defaultViewport": true,
"height": 0,
"viewportBottom": 1,
"viewportLeft": 0,
"viewportRight": 1,
"viewportTop": 0,
"width": 0
}
],
"effects": []
}
],
"behaviorsSharedData": []
}
],
"externalEvents": [],
"externalLayouts": [],
"externalSourceFiles": []
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 143 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 394 B

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 214 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 360 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

File diff suppressed because one or more lines are too long

View File

@@ -425,6 +425,156 @@ Object {
},
},
},
"Pathfinding behavior": Object {
"Destination reached": Object {
"displayedName": "Destination reached",
"fullGroupName": "Pathfinding behavior/",
"type": "PathfindingBehavior::DestinationReached",
},
"Obstacles": Object {
"Cost": Object {
"displayedName": "Cost",
"fullGroupName": "Pathfinding behavior/Obstacles",
"type": "PathfindingBehavior::Cost",
},
"Is object impassable?": Object {
"displayedName": "Is object impassable?",
"fullGroupName": "Pathfinding behavior/Obstacles",
"type": "PathfindingBehavior::IsImpassable",
},
},
"Path": Object {
"Acceleration": Object {
"displayedName": "Acceleration",
"fullGroupName": "Pathfinding behavior/Path",
"type": "PathfindingBehavior::Acceleration",
},
"Angular maximum speed": Object {
"displayedName": "Angular maximum speed",
"fullGroupName": "Pathfinding behavior/Path",
"type": "PathfindingBehavior::AngularMaxSpeed",
},
"Diagonals moves": Object {
"displayedName": "Diagonals moves",
"fullGroupName": "Pathfinding behavior/Path",
"type": "PathfindingBehavior::DiagonalsAllowed",
},
"Extra border": Object {
"displayedName": "Extra border",
"fullGroupName": "Pathfinding behavior/Path",
"type": "PathfindingBehavior::ExtraBorder",
},
"Maximum speed": Object {
"displayedName": "Maximum speed",
"fullGroupName": "Pathfinding behavior/Path",
"type": "PathfindingBehavior::MaxSpeed",
},
"Object rotated": Object {
"displayedName": "Object rotated",
"fullGroupName": "Pathfinding behavior/Path",
"type": "PathfindingBehavior::ObjectRotated",
},
"Rotation offset": Object {
"displayedName": "Rotation offset",
"fullGroupName": "Pathfinding behavior/Path",
"type": "PathfindingBehavior::AngleOffset",
},
"Speed": Object {
"displayedName": "Speed",
"fullGroupName": "Pathfinding behavior/Path",
"type": "PathfindingBehavior::Speed",
},
},
"Path found": Object {
"displayedName": "Path found",
"fullGroupName": "Pathfinding behavior/",
"type": "PathfindingBehavior::PathFound",
},
"Virtual grid": Object {
"Height of the virtual grid": Object {
"displayedName": "Height of the virtual grid",
"fullGroupName": "Pathfinding behavior/Virtual grid",
"type": "PathfindingBehavior::CellHeight",
},
"Width of the virtual grid": Object {
"displayedName": "Width of the virtual grid",
"fullGroupName": "Pathfinding behavior/Virtual grid",
"type": "PathfindingBehavior::CellWidth",
},
},
},
"Physics behavior": Object {
"Collision": Object {
"displayedName": "Collision",
"fullGroupName": "Physics behavior/",
"type": "PhysicsBehavior::CollisionWith",
},
"Collision polygon": Object {
"Collision polygon X scale": Object {
"displayedName": "Collision polygon X scale",
"fullGroupName": "Physics behavior/Collision polygon",
"type": "PhysicsBehavior::GetPolygonScaleX",
},
"Collision polygon Y scale": Object {
"displayedName": "Collision polygon Y scale",
"fullGroupName": "Physics behavior/Collision polygon",
"type": "PhysicsBehavior::GetPolygonScaleY",
},
},
"Displacement": Object {
"Angular damping": Object {
"displayedName": "Angular damping",
"fullGroupName": "Physics behavior/Displacement",
"type": "PhysicsBehavior::AngularDamping",
},
"Linear damping": Object {
"displayedName": "Linear damping",
"fullGroupName": "Physics behavior/Displacement",
"type": "PhysicsBehavior::LinearDamping",
},
"Linear speed": Object {
"displayedName": "Linear speed",
"fullGroupName": "Physics behavior/Displacement",
"type": "PhysicsBehavior::LinearVelocity",
},
"X component": Object {
"displayedName": "X component",
"fullGroupName": "Physics behavior/Displacement",
"type": "PhysicsBehavior::LinearVelocityX",
},
"Y component": Object {
"displayedName": "Y component",
"fullGroupName": "Physics behavior/Displacement",
"type": "PhysicsBehavior::LinearVelocityY",
},
},
"Movement": Object {
"The object is dynamic": Object {
"displayedName": "The object is dynamic",
"fullGroupName": "Physics behavior/Movement",
"type": "PhysicsBehavior::IsDynamic",
},
},
"Other": Object {
"Object is treated like a bullet": Object {
"displayedName": "Object is treated like a bullet",
"fullGroupName": "Physics behavior/Other",
"type": "PhysicsBehavior::IsBullet",
},
},
"Rotation": Object {
"Angular speed": Object {
"displayedName": "Angular speed",
"fullGroupName": "Physics behavior/Rotation",
"type": "PhysicsBehavior::AngularVelocity",
},
"Fixed rotation": Object {
"displayedName": "Fixed rotation",
"fullGroupName": "Physics behavior/Rotation",
"type": "PhysicsBehavior::IsFixedRotation",
},
},
},
"Platform Behavior": Object {
"Is falling": Object {
"displayedName": "Is falling",
@@ -1703,6 +1853,186 @@ Array [
"fullGroupName": "Shopify",
"type": "Shopify::GetCheckoutUrlForProduct",
},
Object {
"displayedName": "Acceleration",
"fullGroupName": "Pathfinding behavior/Path",
"type": "PathfindingBehavior::Acceleration",
},
Object {
"displayedName": "Diagonals moves",
"fullGroupName": "Pathfinding behavior/Path",
"type": "PathfindingBehavior::AllowDiagonals",
},
Object {
"displayedName": "Rotation offset",
"fullGroupName": "Pathfinding behavior/Path",
"type": "PathfindingBehavior::AngleOffset",
},
Object {
"displayedName": "Angular maximum speed",
"fullGroupName": "Pathfinding behavior/Path",
"type": "PathfindingBehavior::AngularMaxSpeed",
},
Object {
"displayedName": "Height of the cells",
"fullGroupName": "Pathfinding behavior/Virtual grid",
"type": "PathfindingBehavior::CellHeight",
},
Object {
"displayedName": "Width of the cells",
"fullGroupName": "Pathfinding behavior/Virtual grid",
"type": "PathfindingBehavior::CellWidth",
},
Object {
"displayedName": "Extra border",
"fullGroupName": "Pathfinding behavior/Path",
"type": "PathfindingBehavior::ExtraBorder",
},
Object {
"displayedName": "Maximum speed",
"fullGroupName": "Pathfinding behavior/Path",
"type": "PathfindingBehavior::MaxSpeed",
},
Object {
"displayedName": "Rotate the object",
"fullGroupName": "Pathfinding behavior/Path",
"type": "PathfindingBehavior::RotateObject",
},
Object {
"displayedName": "Move to a position",
"fullGroupName": "Pathfinding behavior/",
"type": "PathfindingBehavior::SetDestination",
},
Object {
"displayedName": "Speed",
"fullGroupName": "Pathfinding behavior/Path",
"type": "PathfindingBehavior::Speed",
},
Object {
"displayedName": "Cost",
"fullGroupName": "Pathfinding behavior/Obstacles",
"type": "PathfindingBehavior::Cost",
},
Object {
"displayedName": "Should object be impassable?",
"fullGroupName": "Pathfinding behavior/Obstacles",
"type": "PathfindingBehavior::SetImpassable",
},
Object {
"displayedName": "Add a gear between two objects",
"fullGroupName": "Physics behavior/Joints",
"type": "PhysicsBehavior::ActAddGearJointBetweenObjects",
},
Object {
"displayedName": "Add a hinge",
"fullGroupName": "Physics behavior/Joints",
"type": "PhysicsBehavior::AddRevoluteJoint",
},
Object {
"displayedName": "Add a hinge between two objects",
"fullGroupName": "Physics behavior/Joints",
"type": "PhysicsBehavior::AddRevoluteJointBetweenObjects",
},
Object {
"displayedName": "Add a force",
"fullGroupName": "Physics behavior/Displacement",
"type": "PhysicsBehavior::ApplyForce",
},
Object {
"displayedName": "Apply a force toward a position",
"fullGroupName": "Physics behavior/Displacement",
"type": "PhysicsBehavior::ApplyForceTowardPosition",
},
Object {
"displayedName": "Apply a force ( angle )",
"fullGroupName": "Physics behavior/Displacement",
"type": "PhysicsBehavior::ApplyForceUsingPolarCoordinates",
},
Object {
"displayedName": "Apply an impulse",
"fullGroupName": "Physics behavior/Displacement",
"type": "PhysicsBehavior::ApplyImpulse",
},
Object {
"displayedName": "Apply an impulse toward a position",
"fullGroupName": "Physics behavior/Displacement",
"type": "PhysicsBehavior::ApplyImpulseTowardPosition",
},
Object {
"displayedName": "Apply an impulse (angle)",
"fullGroupName": "Physics behavior/Displacement",
"type": "PhysicsBehavior::ApplyImpulseUsingPolarCoordinates",
},
Object {
"displayedName": "Add a torque (a rotation)",
"fullGroupName": "Physics behavior/Rotation",
"type": "PhysicsBehavior::ApplyTorque",
},
Object {
"displayedName": "Do not treat object like a bullet",
"fullGroupName": "Physics behavior/Other",
"type": "PhysicsBehavior::DontSetAsBullet",
},
Object {
"displayedName": "Angular damping",
"fullGroupName": "Physics behavior/Displacement",
"type": "PhysicsBehavior::SetAngularDamping",
},
Object {
"displayedName": "Angular speed",
"fullGroupName": "Physics behavior/Rotation",
"type": "PhysicsBehavior::SetAngularVelocity",
},
Object {
"displayedName": "Treat object like a bullet.",
"fullGroupName": "Physics behavior/Other",
"type": "PhysicsBehavior::SetAsBullet",
},
Object {
"displayedName": "Make the object dynamic",
"fullGroupName": "Physics behavior/Movement",
"type": "PhysicsBehavior::SetDynamic",
},
Object {
"displayedName": "Fix rotation",
"fullGroupName": "Physics behavior/Rotation",
"type": "PhysicsBehavior::SetFixedRotation",
},
Object {
"displayedName": "Make object's rotation free",
"fullGroupName": "Physics behavior/Rotation",
"type": "PhysicsBehavior::SetFreeRotation",
},
Object {
"displayedName": "Gravity",
"fullGroupName": "Physics behavior/Global options",
"type": "PhysicsBehavior::SetGravity",
},
Object {
"displayedName": "Linear damping",
"fullGroupName": "Physics behavior/Displacement",
"type": "PhysicsBehavior::SetLinearDamping",
},
Object {
"displayedName": "Linear velocity",
"fullGroupName": "Physics behavior/Displacement",
"type": "PhysicsBehavior::SetLinearVelocity",
},
Object {
"displayedName": "Change the X scale of a collision polygon",
"fullGroupName": "Physics behavior/Collision polygon",
"type": "PhysicsBehavior::SetPolygonScaleX",
},
Object {
"displayedName": "Change the Y scale of a collision polygon",
"fullGroupName": "Physics behavior/Collision polygon",
"type": "PhysicsBehavior::SetPolygonScaleY",
},
Object {
"displayedName": "Make the object static",
"fullGroupName": "Physics behavior/Movement",
"type": "PhysicsBehavior::SetStatic",
},
]
`;
@@ -2378,5 +2708,135 @@ Array [
"fullGroupName": "System information",
"type": "SystemInfo::IsMobile",
},
Object {
"displayedName": "Acceleration",
"fullGroupName": "Pathfinding behavior/Path",
"type": "PathfindingBehavior::Acceleration",
},
Object {
"displayedName": "Rotation offset",
"fullGroupName": "Pathfinding behavior/Path",
"type": "PathfindingBehavior::AngleOffset",
},
Object {
"displayedName": "Angular maximum speed",
"fullGroupName": "Pathfinding behavior/Path",
"type": "PathfindingBehavior::AngularMaxSpeed",
},
Object {
"displayedName": "Height of the virtual grid",
"fullGroupName": "Pathfinding behavior/Virtual grid",
"type": "PathfindingBehavior::CellHeight",
},
Object {
"displayedName": "Width of the virtual grid",
"fullGroupName": "Pathfinding behavior/Virtual grid",
"type": "PathfindingBehavior::CellWidth",
},
Object {
"displayedName": "Destination reached",
"fullGroupName": "Pathfinding behavior/",
"type": "PathfindingBehavior::DestinationReached",
},
Object {
"displayedName": "Diagonals moves",
"fullGroupName": "Pathfinding behavior/Path",
"type": "PathfindingBehavior::DiagonalsAllowed",
},
Object {
"displayedName": "Extra border",
"fullGroupName": "Pathfinding behavior/Path",
"type": "PathfindingBehavior::ExtraBorder",
},
Object {
"displayedName": "Maximum speed",
"fullGroupName": "Pathfinding behavior/Path",
"type": "PathfindingBehavior::MaxSpeed",
},
Object {
"displayedName": "Object rotated",
"fullGroupName": "Pathfinding behavior/Path",
"type": "PathfindingBehavior::ObjectRotated",
},
Object {
"displayedName": "Path found",
"fullGroupName": "Pathfinding behavior/",
"type": "PathfindingBehavior::PathFound",
},
Object {
"displayedName": "Speed",
"fullGroupName": "Pathfinding behavior/Path",
"type": "PathfindingBehavior::Speed",
},
Object {
"displayedName": "Cost",
"fullGroupName": "Pathfinding behavior/Obstacles",
"type": "PathfindingBehavior::Cost",
},
Object {
"displayedName": "Is object impassable?",
"fullGroupName": "Pathfinding behavior/Obstacles",
"type": "PathfindingBehavior::IsImpassable",
},
Object {
"displayedName": "Angular damping",
"fullGroupName": "Physics behavior/Displacement",
"type": "PhysicsBehavior::AngularDamping",
},
Object {
"displayedName": "Angular speed",
"fullGroupName": "Physics behavior/Rotation",
"type": "PhysicsBehavior::AngularVelocity",
},
Object {
"displayedName": "Collision",
"fullGroupName": "Physics behavior/",
"type": "PhysicsBehavior::CollisionWith",
},
Object {
"displayedName": "Collision polygon X scale",
"fullGroupName": "Physics behavior/Collision polygon",
"type": "PhysicsBehavior::GetPolygonScaleX",
},
Object {
"displayedName": "Collision polygon Y scale",
"fullGroupName": "Physics behavior/Collision polygon",
"type": "PhysicsBehavior::GetPolygonScaleY",
},
Object {
"displayedName": "Object is treated like a bullet",
"fullGroupName": "Physics behavior/Other",
"type": "PhysicsBehavior::IsBullet",
},
Object {
"displayedName": "The object is dynamic",
"fullGroupName": "Physics behavior/Movement",
"type": "PhysicsBehavior::IsDynamic",
},
Object {
"displayedName": "Fixed rotation",
"fullGroupName": "Physics behavior/Rotation",
"type": "PhysicsBehavior::IsFixedRotation",
},
Object {
"displayedName": "Linear damping",
"fullGroupName": "Physics behavior/Displacement",
"type": "PhysicsBehavior::LinearDamping",
},
Object {
"displayedName": "Linear speed",
"fullGroupName": "Physics behavior/Displacement",
"type": "PhysicsBehavior::LinearVelocity",
},
Object {
"displayedName": "X component",
"fullGroupName": "Physics behavior/Displacement",
"type": "PhysicsBehavior::LinearVelocityX",
},
Object {
"displayedName": "Y component",
"fullGroupName": "Physics behavior/Displacement",
"type": "PhysicsBehavior::LinearVelocityY",
},
]
`;

View File

@@ -5,6 +5,7 @@ import BrowserPreviewLinkDialog from './BrowserPreviewLinkDialog';
import { findGDJS } from './BrowserS3GDJSFinder';
import assignIn from 'lodash/assignIn';
import { GDevelopGamesPreview } from '../../Utils/GDevelopServices/ApiConfigs';
import { makeTimestampedId } from '../../Utils/TimestampedId';
const awsS3 = require('aws-sdk/clients/s3');
const gd = global.gd;
@@ -41,8 +42,7 @@ export default class BrowserS3PreviewLauncher {
}
console.info('GDJS found in ', gdjsRoot);
const prefix =
'' + Date.now() + '-' + Math.floor(Math.random() * 1000000);
const prefix = makeTimestampedId();
const outputDir = destinationBucketBaseUrl + prefix;
const browserS3FileSystem = new BrowserS3FileSystem({

View File

@@ -9,6 +9,9 @@ import { findGDJS } from './LocalGDJSFinder';
import localFileSystem from './LocalFileSystem';
import LocalFolderPicker from '../../UI/LocalFolderPicker';
import HelpButton from '../../UI/HelpButton';
import { displaySanityCheck } from '../SanityChecker';
import { getSanityMessages } from '../SanityChecker/CordovaSanityChecker';
import { translate } from 'react-i18next';
import assignIn from 'lodash/assignIn';
import optionalRequire from '../../Utils/OptionalRequire';
import Window from '../../Utils/Window';
@@ -17,7 +20,7 @@ const shell = electron ? electron.shell : null;
const gd = global.gd;
export default class LocalCordovaExport extends Component {
class LocalCordovaExport extends Component {
state = {
exportFinishedDialogOpen: false,
outputDir: '',
@@ -53,11 +56,13 @@ export default class LocalCordovaExport extends Component {
};
launchExport = () => {
const { project } = this.props;
const { t, project } = this.props;
if (!project) return;
sendExportLaunched('local-cordova');
if (!displaySanityCheck(t, getSanityMessages(t, project))) return;
const outputDir = this.state.outputDir;
project.setLastCompilationDirectory(outputDir);
@@ -89,7 +94,7 @@ export default class LocalCordovaExport extends Component {
};
render() {
const { project } = this.props;
const { t, project } = this.props;
if (!project) return null;
return (
@@ -125,7 +130,7 @@ export default class LocalCordovaExport extends Component {
/>
</Line>
<Dialog
title="Export finished"
title={t('Export finished')}
actions={[
<FlatButton
key="open"
@@ -162,10 +167,12 @@ export default class LocalCordovaExport extends Component {
fullWidth
primary
onClick={() => this.openPhoneGapBuild()}
label="Open PhoneGap Build"
label={t('Open PhoneGap Build')}
/>
</Dialog>
</Column>
);
}
}
export default translate()(LocalCordovaExport);

View File

@@ -25,6 +25,9 @@ import Window from '../../../Utils/Window';
import { delay } from '../../../Utils/Delay';
import CreateProfile from '../../../Profile/CreateProfile';
import LimitDisplayer from '../../../Profile/LimitDisplayer';
import { displaySanityCheck } from '../../SanityChecker';
import { getSanityMessages } from '../../SanityChecker/CordovaSanityChecker';
import { translate, type TranslatorProps } from 'react-i18next';
const path = optionalRequire('path');
const os = optionalRequire('os');
const electron = optionalRequire('electron');
@@ -51,7 +54,7 @@ type State = {
errored: boolean,
};
type Props = WithUserProfileProps & {
type Props = WithUserProfileProps & TranslatorProps & {
project: gdProject,
onChangeSubscription: Function,
};
@@ -97,7 +100,7 @@ class LocalOnlineCordovaExport extends Component<Props, State> {
};
launchExport = (): Promise<string> => {
const { project } = this.props;
const { project, t } = this.props;
if (!project) return Promise.reject();
return LocalOnlineCordovaExport.prepareExporter()
@@ -114,7 +117,7 @@ class LocalOnlineCordovaExport extends Component<Props, State> {
return outputDir;
})
.catch(err => {
showErrorBox('Unable to export the game', err);
showErrorBox(t('Unable to export the game'), err);
throw err;
});
};
@@ -198,8 +201,12 @@ class LocalOnlineCordovaExport extends Component<Props, State> {
};
launchWholeExport = () => {
const { t, project } = this.props;
sendExportLaunched('local-online-cordova');
if (!displaySanityCheck(t, getSanityMessages(t, project)))
return;
const handleError = (message: string) => err => {
if (!this.state.errored) {
this.setState({
@@ -226,33 +233,33 @@ class LocalOnlineCordovaExport extends Component<Props, State> {
exportStep: 'compress',
});
return this.launchCompression(outputDir);
}, handleError('Error while exporting the game.'))
}, handleError(t('Error while exporting the game.')))
.then(outputFile => {
this.setState({
exportStep: 'upload',
});
return this.launchUpload(outputFile);
}, handleError('Error while compressing the game.'))
}, handleError(t('Error while compressing the game.')))
.then((uploadBucketKey: string) => {
this.setState({
exportStep: 'waiting-for-build',
});
return this.launchBuild(uploadBucketKey);
}, handleError('Error while uploading the game. Check your internet connection or try again later.'))
}, handleError(t('Error while uploading the game. Check your internet connection or try again later.')))
.then(buildId => {
this.setState({
exportStep: 'build',
});
return this.pollBuild(buildId);
}, handleError('Error while lauching the build of the game.'))
}, handleError(t('Error while lauching the build of the game.')))
.then(build => {
this.setState({
exportStep: 'done',
build,
});
this.props.onRefreshUserProfile();
}, handleError('Error while building the game.'));
}, handleError(t('Error while building the game.')));
};
_download = () => {
@@ -291,6 +298,7 @@ class LocalOnlineCordovaExport extends Component<Props, State> {
onLogin,
subscription,
limits,
t,
} = this.props;
if (!project) return null;
@@ -302,13 +310,12 @@ class LocalOnlineCordovaExport extends Component<Props, State> {
return (
<Column noMargin>
<Line>
Packaging your game for Android will create an APK file that can be
installed on Android phones, based on Cordova framework.
{t("Packaging your game for Android will create an APK file that can be installed on Android phones, based on Cordova framework.")}
</Line>
{authenticated && (
<Line justifyContent="center">
<RaisedButton
label="Package for Android"
label={t("Package for Android")}
primary
onClick={this.launchWholeExport}
disabled={disableBuild}
@@ -324,7 +331,7 @@ class LocalOnlineCordovaExport extends Component<Props, State> {
)}
{!authenticated && (
<CreateProfile
message="Create an account to build your game for Android in one-click:"
message={t("Create an account to build your game for Android in one-click:")}
onLogin={onLogin}
/>
)}
@@ -347,6 +354,6 @@ class LocalOnlineCordovaExport extends Component<Props, State> {
}
}
export default withUserProfile({ fetchLimits: true, fetchSubscription: true })(
export default translate()(withUserProfile({ fetchLimits: true, fetchSubscription: true })(
LocalOnlineCordovaExport
);
));

View File

@@ -8,6 +8,7 @@ import optionalRequire from '../../Utils/OptionalRequire';
import { Column, Line, Spacer } from '../../UI/Grid';
import LinearProgress from 'material-ui/LinearProgress';
import { GDevelopHostingApi } from '../../Utils/GDevelopServices/ApiConfigs';
import { makeTimestampedId } from '../../Utils/TimestampedId';
import TextField from 'material-ui/TextField';
const os = optionalRequire('os');
const electron = optionalRequire('electron');
@@ -31,11 +32,13 @@ export default class LocalS3Export extends Component {
ipcRenderer.removeAllListeners('s3-folder-upload-done');
return new Promise((resolve, reject) => {
ipcRenderer.on('s3-folder-upload-progress', (event, uploadProgress, uploadMax) =>
this.setState({
uploadProgress,
uploadMax,
})
ipcRenderer.on(
's3-folder-upload-progress',
(event, uploadProgress, uploadMax) =>
this.setState({
uploadProgress,
uploadMax,
})
);
ipcRenderer.on('s3-folder-upload-done', (event, err, prefix) => {
if (err) return reject(err);
@@ -51,7 +54,8 @@ export default class LocalS3Export extends Component {
_deploy = prefix => {
return sleep(200)
.then(() => //TODO: Move this to a GDevelopServices/Hosting.js file
.then(() =>
//TODO: Move this to a GDevelopServices/Hosting.js file
axios(GDevelopHostingApi.deployEndpoint, {
method: 'post',
params: {
@@ -79,7 +83,7 @@ export default class LocalS3Export extends Component {
deployDone: false,
});
const outputDir = os.tmpdir() + '/GDS3Export';
const outputDir = os.tmpdir() + '/GDS3Export-' + makeTimestampedId();
LocalExport.prepareExporter()
.then(({ exporter }) => {
const exportForCordova = false;

View File

@@ -0,0 +1,30 @@
// @flow
import { type TFunction } from 'react-i18next';
import { type SanityMessages } from './index';
export const getSanityMessages = (t: TFunction, project: gdProject): SanityMessages => {
let errors = [];
let warnings = [];
if (!project.getPackageName()) {
errors.push(
t(
'The package name is empty. Choose and enter a package name in the game properties.'
)
);
} else if (project.getPackageName().length >= 255) {
errors.push(t('The package name is too long.'));
}
if (!project.getName()) {
errors.push(
t(
'The game name is empty. Choose and enter a name in the game properties.'
)
);
}
return {
errors,
warnings,
};
};

View File

@@ -0,0 +1,25 @@
// @flow
import { type TFunction } from 'react-i18next';
import { showErrorBox } from '../../UI/Messages/MessageBox';
export type SanityMessages = {
errors: Array<string>,
warnings: Array<string>,
};
export const displaySanityCheck = (
t: TFunction,
messages: SanityMessages
): boolean => {
if (messages.errors.length) {
showErrorBox(
t(
'Your game has some invalid elements, please fix these before continuing:'
) +
'\n\n' +
messages.errors.map(message => `- ${message}`).join('\n')
);
}
return !messages.errors.length;
};

View File

@@ -0,0 +1,21 @@
import React from 'react';
import BaseEditor from './BaseEditor';
import ResourcesFullEditor from '../../ResourcesEditor';
export default class ResourcesEditor extends BaseEditor {
updateToolbar() {
if (this.editor) this.editor.updateToolbar();
}
render() {
const { project } = this.props;
return (
<ResourcesFullEditor
{...this.props}
ref={editor => (this.editor = editor)}
project={project}
/>
);
}
}

View File

@@ -47,6 +47,7 @@ import ExternalEventsEditor from './Editors/ExternalEventsEditor';
import SceneEditor from './Editors/SceneEditor';
import ExternalLayoutEditor from './Editors/ExternalLayoutEditor';
import StartPage from './Editors/StartPage';
import ResourcesEditor from './Editors/ResourcesEditor';
import {
type PreferencesState,
getThemeName,
@@ -241,7 +242,11 @@ export default class MainFrame extends Component<*, State> {
const name = newNameGenerator('NewScene', name =>
currentProject.hasLayoutNamed(name)
);
currentProject.insertNewLayout(name, currentProject.getLayoutsCount());
const newLayout = currentProject.insertNewLayout(
name,
currentProject.getLayoutsCount()
);
newLayout.updateBehaviorsSharedData(currentProject);
this.forceUpdate();
};
@@ -541,6 +546,36 @@ export default class MainFrame extends Component<*, State> {
);
};
openResources = () => {
this.setState(
{
editorTabs: openEditorTab(this.state.editorTabs, {
name: 'Resources',
editorCreator: () => (
<ResourcesEditor
project={this.state.currentProject}
setToolbar={this.setEditorToolbar}
onDeleteResource={(resource: gdResource, cb: boolean => void) => {
// TODO: Project wide refactoring of objects/events using the resource
cb(true);
}}
onRenameResource={(
resource: gdResource,
newName: string,
cb: boolean => void
) => {
// TODO: Project wide refactoring of objects/events using the resource
cb(true);
}}
/>
),
key: 'resources',
}),
},
() => this.updateToolbar()
);
};
openStartPage = () => {
this.setState(
{
@@ -810,6 +845,7 @@ export default class MainFrame extends Component<*, State> {
onCloseProject={this.askToCloseProject}
onExportProject={this.openExportDialog}
onOpenPreferences={() => this.openPreferences(true)}
onOpenResources={() => this.openResources()}
/>
)}
</Drawer>
@@ -908,7 +944,7 @@ export default class MainFrame extends Component<*, State> {
open={profileDialogOpen}
authentification={authentification}
onClose={() => this.openProfile(false)}
onChangeSubscription={(onDone) => this.openSubscription(true, onDone)}
onChangeSubscription={onDone => this.openSubscription(true, onDone)}
/>
<SubscriptionDialog
onClose={() => {

View File

@@ -1,6 +1,6 @@
import React from 'react';
import ResourcesLoader from '../ObjectsRendering/ResourcesLoader';
import ResourceSelector from '../ResourcesEditor/ResourceSelector';
import ResourceSelector from '../ResourcesList/ResourceSelector';
import ImageThumbnail from './ImageThumbnail';
export default ({

View File

@@ -257,7 +257,7 @@ export default class ObjectsListContainer extends React.Component<
const { object: pasteObject, global } = objectWithContext;
const { object: copiedObject, type, name } = Clipboard.get(CLIPBOARD_KIND);
const { project, objectsContainer } = this.props;
const { project, objectsContainer, onObjectPasted } = this.props;
const newName = newNameGenerator(
'CopyOf' + name,
@@ -287,6 +287,7 @@ export default class ObjectsListContainer extends React.Component<
);
this.forceUpdate();
if (onObjectPasted) onObjectPasted(newObject);
};
_editName = (objectWithContext: ?ObjectWithContext) => {

View File

@@ -22,7 +22,7 @@ export default class PixiResourcesLoader {
const resourcesManager = project.getResourcesManager();
const loader = PIXI.loader;
const resourcesList = resourcesManager.getAllResourcesList().toJSArray();
const resourcesList = resourcesManager.getAllResourceNames().toJSArray();
const allResources = {};
resourcesList.forEach(resourceName => {
const resource = resourcesManager.getResource(resourceName);

View File

@@ -17,6 +17,7 @@ import Authentification, {
import LoginDialog from './LoginDialog';
import { watchPromiseInState } from '../Utils/WatchPromiseInState';
import { showWarningBox } from '../UI/Messages/MessageBox';
import { sendSignupDone } from '../Utils/Analytics/EventSender';
type Props = {
open: boolean,
@@ -181,6 +182,7 @@ export const withUserProfile = (
() => {
this._fetchUserProfile();
this.openLogin(false);
sendSignupDone(form.email);
},
(loginError: LoginError) => {
this.setState({

View File

@@ -1,5 +1,6 @@
import React, { Component } from 'react';
import FlatButton from 'material-ui/FlatButton';
import Subheader from 'material-ui/Subheader';
import { List, ListItem } from 'material-ui/List';
import { sendNewGameCreated } from '../Utils/Analytics/EventSender';
import { Column, Line } from '../UI/Grid';
@@ -13,25 +14,66 @@ export default class LocalCreateDialog extends Component {
</Column>
</Line>
<Line>
<Column expand>
<FlatButton
label="Platformer"
fullWidth
primary
onClick={() => {
sendNewGameCreated('platformer');
this.props.onOpen('internal://platformer');
}}
/>
<FlatButton
label="Space Shooter"
fullWidth
primary
onClick={() => {
sendNewGameCreated('space-shooter');
this.props.onOpen('internal://space-shooter');
}}
/>
<Column expand noMargin>
<List>
<Subheader>Starters</Subheader>
<ListItem
primaryText="Platformer"
secondaryText={
<p>
A simple platform game, with coins to collect, moving
platforms and enemies.
</p>
}
secondaryTextLines={2}
onClick={() => {
sendNewGameCreated('platformer');
this.props.onOpen('internal://platformer');
}}
/>
<ListItem
primaryText="Space Shooter"
secondaryText={
<p>
A side-scrolling shooter where you must defeat incoming
enemies with your spaceship.
</p>
}
secondaryTextLines={2}
onClick={() => {
sendNewGameCreated('space-shooter');
this.props.onOpen('internal://space-shooter');
}}
/>
<Subheader>Examples</Subheader>
<ListItem
primaryText="Physics"
secondaryText={
<p>
Example showing how to configure physics behavior on objects and use events to detect collisions.
</p>
}
secondaryTextLines={2}
onClick={() => {
sendNewGameCreated('physics');
this.props.onOpen('internal://physics');
}}
/>
<ListItem
primaryText="Pathfinding"
secondaryText={
<p>
Example showing how to move a tank avoiding obstacles on the
battlefield.
</p>
}
secondaryTextLines={2}
onClick={() => {
sendNewGameCreated('pathfinding');
this.props.onOpen('internal://pathfinding');
}}
/>
</List>
</Column>
</Line>
</Column>

View File

@@ -1,5 +1,6 @@
import React, { Component } from 'react';
import Divider from 'material-ui/Divider';
import Subheader from 'material-ui/Subheader';
import LocalFolderPicker from '../UI/LocalFolderPicker';
import { sendNewGameCreated } from '../Utils/Analytics/EventSender';
import { Column, Line } from '../UI/Grid';
@@ -74,6 +75,7 @@ export default class LocalCreateDialog extends Component {
<Line>
<Column expand noMargin>
<List>
<Subheader>Starters</Subheader>
<ListItem
primaryText="Platformer"
secondaryText={
@@ -102,6 +104,31 @@ export default class LocalCreateDialog extends Component {
secondaryTextLines={2}
onClick={() => this.createEmptyGame()}
/>
<Subheader>Examples</Subheader>
<ListItem
primaryText="Physics"
secondaryText={<p>Example showing how to configure physics behavior on objects and use events to detect collisions.</p>}
secondaryTextLines={2}
onClick={() => this.createFromExample('physics')}
/>
<ListItem
primaryText="Pathfinding"
secondaryText={<p>Example showing how to move a tank avoiding obstacles on the battlefield.</p>}
secondaryTextLines={2}
onClick={() => this.createFromExample('pathfinding')}
/>
<ListItem
primaryText="Zombie laser"
secondaryText={<p>Example with procedural terrain generation, laser with Shape painter object and usage of pathfinding to move zombies toward the player.</p>}
secondaryTextLines={2}
onClick={() => this.createFromExample('zombie-laser')}
/>
<ListItem
primaryText="Parallax background"
secondaryText={<p>Very simple example showing how to have a background with multiple layers and a parallax effect.</p>}
secondaryTextLines={2}
onClick={() => this.createFromExample('parallax')}
/>
</List>
</Column>
</Line>

View File

@@ -1,21 +1,6 @@
// @flow
import { mapFor } from '../Utils/MapFor';
//TODO: Layout, ExternalEvents and ExternalLayout should be moved to a common type definition file
//for all GDevelop.js
type Layout = {
getName: Function,
setName: Function,
};
type ExternalLayout = {
getName: Function,
setName: Function,
};
type ExternalEvents = {
getName: Function,
setName: Function,
};
export const enumerateLayouts = (project: any) =>
mapFor(0, project.getLayoutsCount(), i => project.getLayoutAt(i));
@@ -30,7 +15,7 @@ export const enumerateExternalLayouts = (project: any) =>
);
export const filterProjectItemsList = (
list: Array<Layout> | Array<ExternalLayout> | Array<ExternalEvents>,
list: Array<gdLayout> | Array<gdExternalLayout> | Array<gdExternalEvents>,
searchText: string
) => {
if (!searchText) return list;

View File

@@ -1,4 +1,5 @@
import React, { Component } from 'react';
// @flow
import * as React from 'react';
import { List, ListItem } from 'material-ui/List';
import TextField from 'material-ui/TextField';
import SearchBar from 'material-ui-search-bar';
@@ -65,7 +66,10 @@ const ThemableProjectStructureItem = ({ muiTheme, ...otherProps }) => (
const ProjectStructureItem = muiThemeable()(ThemableProjectStructureItem);
class ThemableItem extends Component {
class ThemableItem extends React.Component<*, *> {
textField: ?Object;
_iconMenu: ?Object;
componentDidUpdate(prevProps) {
if (!prevProps.editingName && this.props.editingName) {
setTimeout(() => {
@@ -126,7 +130,7 @@ class ThemableItem extends Component {
onKeyPress={event => {
if (event.charCode === 13) {
// enter key pressed
this.textField.blur();
if (this.textField) this.textField.blur();
this.props.onRename(event.target.value);
}
}}
@@ -157,33 +161,64 @@ const Item = muiThemeable()(ThemableItem);
const AddItem = makeAddItem(ListItem);
export default class ProjectManager extends React.Component {
type Props = {
project: gdProject,
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,
onSaveProject: () => void,
onCloseProject: () => void,
onExportProject: () => void,
onOpenPreferences: () => void,
onOpenResources: () => void,
onAddLayout: () => void,
onAddExternalEvents: () => void,
onAddExternalLayout: () => void,
};
type State = {|
renamedItemKind: ?string,
renamedItemName: string,
searchText: string,
projectPropertiesDialogOpen: boolean,
variablesEditorOpen: boolean,
|};
export default class ProjectManager extends React.Component<Props, State> {
state = {
renamedItemKind: null,
renamedItemName: '',
searchText: '',
projectPropertiesDialogOpen: false,
variablesEditorOpen: false,
};
_onEditName = (kind, name) => {
_onEditName = (kind: ?string, name: string) => {
this.setState({
renamedItemKind: kind,
renamedItemName: name,
});
};
_copyLayout = layout => {
_copyLayout = (layout: gdLayout) => {
Clipboard.set(LAYOUT_CLIPBOARD_KIND, {
layout: serializeToJSObject(layout),
name: layout.getName(),
});
};
_cutLayout = layout => {
_cutLayout = (layout: gdLayout) => {
this._copyLayout(layout);
this.props.onDeleteLayout(layout);
};
_pasteLayout = index => {
_pasteLayout = (index: number) => {
if (!Clipboard.has(LAYOUT_CLIPBOARD_KIND)) return;
const { layout: copiedLayout, name } = Clipboard.get(LAYOUT_CLIPBOARD_KIND);
@@ -202,23 +237,24 @@ export default class ProjectManager extends React.Component {
project
);
newLayout.setName(newName);
newLayout.updateBehaviorsSharedData(project);
this.forceUpdate();
};
_copyExternalEvents = externalEvents => {
_copyExternalEvents = (externalEvents: gdExternalEvents) => {
Clipboard.set(EXTERNAL_EVENTS_CLIPBOARD_KIND, {
externalEvents: serializeToJSObject(externalEvents),
name: externalEvents.getName(),
});
};
_cutExternalEvents = externalEvents => {
_cutExternalEvents = (externalEvents: gdExternalEvents) => {
this._copyExternalEvents(externalEvents);
this.props.onDeleteExternalEvents(externalEvents);
};
_pasteExternalEvents = index => {
_pasteExternalEvents = (index: number) => {
if (!Clipboard.has(EXTERNAL_EVENTS_CLIPBOARD_KIND)) return;
const { externalEvents: copiedExternalEvents, name } = Clipboard.get(
@@ -243,19 +279,19 @@ export default class ProjectManager extends React.Component {
this.forceUpdate();
};
_copyExternalLayout = externalLayout => {
_copyExternalLayout = (externalLayout: gdExternalLayout) => {
Clipboard.set(EXTERNAL_LAYOUT_CLIPBOARD_KIND, {
externalLayout: serializeToJSObject(externalLayout),
name: externalLayout.getName(),
});
};
_cutExternalLayout = externalLayout => {
_cutExternalLayout = (externalLayout: gdExternalLayout) => {
this._copyExternalLayout(externalLayout);
this.props.onDeleteExternalLayout(externalLayout);
};
_pasteExternalLayout = index => {
_pasteExternalLayout = (index: number) => {
if (!Clipboard.has(EXTERNAL_LAYOUT_CLIPBOARD_KIND)) return;
const { externalLayout: copiedExternalLayout, name } = Clipboard.get(
@@ -327,10 +363,6 @@ export default class ProjectManager extends React.Component {
<div style={styles.container}>
<List style={styles.list}>
{this._renderMenu()}
{/* <ProjectStructureItem
primaryText="Resources"
leftIcon={<ListIcon src="res/ribbon_default/image32.png" />}
/> */}
<ProjectStructureItem
primaryText="Game settings"
leftIcon={
@@ -353,6 +385,12 @@ export default class ProjectManager extends React.Component {
leftIcon={<ListIcon src="res/ribbon_default/editname32.png" />}
onClick={() => this.setState({ variablesEditorOpen: true })}
/>,
<ListItem
key="resources"
primaryText="Resources"
leftIcon={<ListIcon src="res/ribbon_default/image32.png" />}
onClick={() => this.props.onOpenResources()}
/>,
]}
/>
<ProjectStructureItem
@@ -366,7 +404,7 @@ export default class ProjectManager extends React.Component {
enumerateLayouts(project),
searchText
)
.map((layout, i) => {
.map((layout: gdLayout, i: number) => {
const name = layout.getName();
return (
<Item

Some files were not shown because too many files have changed in this diff Show More