mirror of
https://github.com/4ian/GDevelop.git
synced 2025-10-15 10:19:04 +00:00
Compare commits
4 Commits
v5.0.0-bet
...
v5.0.0-bet
Author | SHA1 | Date | |
---|---|---|---|
![]() |
bdbf7fd9fc | ||
![]() |
6bbedbd8f9 | ||
![]() |
648bd1ff2e | ||
![]() |
d4288caedb |
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@@ -70,7 +70,8 @@
|
||||
"ratio": "cpp",
|
||||
"atomic": "cpp",
|
||||
"locale": "cpp",
|
||||
"string_view": "cpp"
|
||||
"string_view": "cpp",
|
||||
"__string": "cpp"
|
||||
},
|
||||
"files.exclude": {
|
||||
"Binaries/*build*": true,
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
||||
}
|
||||
|
@@ -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.
|
||||
*/
|
||||
|
@@ -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));
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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>() )
|
||||
{
|
||||
|
@@ -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>() )
|
||||
{
|
||||
|
@@ -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);
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
|
@@ -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
|
||||
);
|
||||
));
|
||||
|
30
newIDE/app/src/Export/SanityChecker/CordovaSanityChecker.js
Normal file
30
newIDE/app/src/Export/SanityChecker/CordovaSanityChecker.js
Normal 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,
|
||||
};
|
||||
};
|
25
newIDE/app/src/Export/SanityChecker/index.js
Normal file
25
newIDE/app/src/Export/SanityChecker/index.js
Normal 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;
|
||||
};
|
@@ -241,7 +241,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();
|
||||
};
|
||||
|
||||
@@ -908,7 +912,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={() => {
|
||||
|
@@ -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) => {
|
||||
|
@@ -202,6 +202,7 @@ export default class ProjectManager extends React.Component {
|
||||
project
|
||||
);
|
||||
newLayout.setName(newName);
|
||||
newLayout.updateBehaviorsSharedData(project);
|
||||
|
||||
this.forceUpdate();
|
||||
};
|
||||
|
@@ -1,9 +1,14 @@
|
||||
import React, { Component } from 'react';
|
||||
import FlatButton from 'material-ui/FlatButton';
|
||||
import TextField from 'material-ui/TextField';
|
||||
import Dialog from '../../UI/Dialog';
|
||||
import RaisedButton from 'material-ui/RaisedButton';
|
||||
import Dialog from '../../UI/Dialog';
|
||||
import ColorField from '../../UI/ColorField';
|
||||
import EmptyMessage from '../../UI/EmptyMessage';
|
||||
import PropertiesEditor from '../../PropertiesEditor';
|
||||
import propertiesMapToSchema from '../../PropertiesEditor/PropertiesMapToSchema';
|
||||
import some from 'lodash/some';
|
||||
const gd = global.gd;
|
||||
|
||||
export default class ScenePropertiesDialog extends Component {
|
||||
constructor(props) {
|
||||
@@ -43,20 +48,49 @@ export default class ScenePropertiesDialog extends Component {
|
||||
};
|
||||
|
||||
render() {
|
||||
const { layout, project } = this.props;
|
||||
const actions = [
|
||||
// TODO: Add support for cancelling modifications made to BehaviorSharedData
|
||||
// (either by enhancing a function like propertiesMapToSchema or using copies)
|
||||
// and then re-enable cancel button.
|
||||
// <FlatButton
|
||||
// label="Cancel"
|
||||
// primary={false}
|
||||
// onClick={this.props.onClose}
|
||||
// />,
|
||||
<FlatButton
|
||||
label="Cancel"
|
||||
primary={false}
|
||||
onClick={this.props.onClose}
|
||||
/>,
|
||||
<FlatButton
|
||||
label="Apply"
|
||||
label="Ok"
|
||||
primary={true}
|
||||
keyboardFocused={true}
|
||||
onClick={this._onApply}
|
||||
/>,
|
||||
];
|
||||
|
||||
const allBehaviorSharedDataNames = layout
|
||||
.getAllBehaviorSharedDataNames()
|
||||
.toJSArray();
|
||||
|
||||
const propertiesEditors = allBehaviorSharedDataNames.map(name => {
|
||||
const sharedData = layout.getBehaviorSharedData(name);
|
||||
|
||||
const properties = sharedData.getProperties(project);
|
||||
const propertiesSchema = propertiesMapToSchema(
|
||||
properties,
|
||||
sharedData => sharedData.getProperties(project),
|
||||
(sharedData, name, value) =>
|
||||
sharedData.updateProperty(name, value, project)
|
||||
);
|
||||
|
||||
return (
|
||||
!!propertiesSchema.length && (
|
||||
<PropertiesEditor
|
||||
schema={propertiesSchema}
|
||||
instances={[sharedData]}
|
||||
/>
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
actions={actions}
|
||||
@@ -88,6 +122,13 @@ export default class ScenePropertiesDialog extends Component {
|
||||
this.props.onClose();
|
||||
}}
|
||||
/>
|
||||
{!some(propertiesEditors) && (
|
||||
<EmptyMessage>
|
||||
Any additional properties will appear here if you add behaviors to
|
||||
objects, like Physics behavior.
|
||||
</EmptyMessage>
|
||||
)}
|
||||
{propertiesEditors}
|
||||
{this.props.onOpenMoreSettings && (
|
||||
<RaisedButton
|
||||
label="Open advanced settings"
|
||||
|
@@ -279,9 +279,12 @@ export default class InstancesFullEditor extends Component {
|
||||
};
|
||||
|
||||
_onInstancesMoved = instances => {
|
||||
this.setState({
|
||||
history: saveToHistory(this.state.history, this.props.initialInstances),
|
||||
}, () => this.forceUpdatePropertiesEditor());
|
||||
this.setState(
|
||||
{
|
||||
history: saveToHistory(this.state.history, this.props.initialInstances),
|
||||
},
|
||||
() => this.forceUpdatePropertiesEditor()
|
||||
);
|
||||
};
|
||||
|
||||
_onInstancesModified = instances => {
|
||||
@@ -476,6 +479,11 @@ export default class InstancesFullEditor extends Component {
|
||||
});
|
||||
};
|
||||
|
||||
updateBehaviorsSharedData = () => {
|
||||
const { layout, project } = this.props;
|
||||
layout.updateBehaviorsSharedData(project);
|
||||
};
|
||||
|
||||
forceUpdateObjectsList = () => {
|
||||
if (this._objectsList) this._objectsList.forceUpdateList();
|
||||
};
|
||||
@@ -544,6 +552,7 @@ export default class InstancesFullEditor extends Component {
|
||||
onEditObject={this.props.onEditObject || this.editObject}
|
||||
onDeleteObject={this._onDeleteObject}
|
||||
onRenameObject={this._onRenameObject}
|
||||
onObjectPasted={() => this.updateBehaviorsSharedData()}
|
||||
ref={objectsList => (this._objectsList = objectsList)}
|
||||
/>
|
||||
</MosaicWindow>
|
||||
@@ -581,6 +590,7 @@ export default class InstancesFullEditor extends Component {
|
||||
onCancel={() => this.editObject(null)}
|
||||
onApply={() => {
|
||||
this.editObject(null);
|
||||
this.updateBehaviorsSharedData();
|
||||
this.forceUpdateObjectsList();
|
||||
}}
|
||||
/>
|
||||
@@ -672,6 +682,7 @@ export default class InstancesFullEditor extends Component {
|
||||
/>
|
||||
<ScenePropertiesDialog
|
||||
open={!!this.state.scenePropertiesDialogOpen}
|
||||
project={project}
|
||||
layout={layout}
|
||||
onClose={() => this.openSceneProperties(false)}
|
||||
onApply={() => this.openSceneProperties(false)}
|
||||
|
@@ -3,6 +3,10 @@ import i18n from 'i18next';
|
||||
i18n.init({
|
||||
fallbackLng: 'en',
|
||||
|
||||
// allow keys to be phrases having `:`, `.`
|
||||
nsSeparator: false,
|
||||
keySeparator: false,
|
||||
|
||||
interpolation: {
|
||||
escapeValue: false, // Not needed for react
|
||||
},
|
||||
|
@@ -1,4 +1,4 @@
|
||||
require('dotenv').config();
|
||||
require('dotenv').config({ path: __dirname + '/.env' });
|
||||
const electron = require('electron');
|
||||
const app = electron.app; // Module to control application life.
|
||||
const BrowserWindow = electron.BrowserWindow; // Module to create native browser window.
|
||||
|
7
newIDE/electron-app/app/package-lock.json
generated
7
newIDE/electron-app/app/package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "gdevelop",
|
||||
"version": "5.0.0-beta19",
|
||||
"version": "5.0.0-beta21",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@@ -215,6 +215,11 @@
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"dotenv": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-4.0.0.tgz",
|
||||
"integrity": "sha1-hk7xN5rO1Vzm+V3r7NzhefegzR0="
|
||||
},
|
||||
"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",
|
||||
|
@@ -2,7 +2,7 @@
|
||||
"name": "gdevelop",
|
||||
"productName": "GDevelop 5",
|
||||
"description": "GDevelop 5 IDE running on the Electron runtime",
|
||||
"version": "5.0.0-beta21",
|
||||
"version": "5.0.0-beta22",
|
||||
"author": "Florian Rival",
|
||||
"license": "MIT",
|
||||
"homepage": "http://compilgames.net",
|
||||
@@ -18,6 +18,7 @@
|
||||
"fs-extra": "^3.0.1",
|
||||
"lodash.throttle": "^4.1.1",
|
||||
"minimist": "^1.2.0",
|
||||
"recursive-readdir": "^2.2.1"
|
||||
"recursive-readdir": "^2.2.1",
|
||||
"dotenv": "^4.0.0"
|
||||
}
|
||||
}
|
||||
|
3
newIDE/electron-app/package-lock.json
generated
3
newIDE/electron-app/package-lock.json
generated
@@ -664,7 +664,8 @@
|
||||
"dotenv": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-4.0.0.tgz",
|
||||
"integrity": "sha1-hk7xN5rO1Vzm+V3r7NzhefegzR0="
|
||||
"integrity": "sha1-hk7xN5rO1Vzm+V3r7NzhefegzR0=",
|
||||
"dev": true
|
||||
},
|
||||
"dotenv-expand": {
|
||||
"version": "4.0.1",
|
||||
|
@@ -41,7 +41,6 @@
|
||||
"shelljs": "^0.7.7"
|
||||
},
|
||||
"dependencies": {
|
||||
"dotenv": "^4.0.0",
|
||||
"electron-is": "^2.4.0"
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user