mirror of
https://github.com/4ian/GDevelop.git
synced 2025-10-15 10:19:04 +00:00
Compare commits
21 Commits
v5.3.194
...
feat/updat
Author | SHA1 | Date | |
---|---|---|---|
![]() |
5193b617b3 | ||
![]() |
1bb473b0b0 | ||
![]() |
4376b4f36e | ||
![]() |
6ecbae9c35 | ||
![]() |
93e9fc6aed | ||
![]() |
7c0a7a4152 | ||
![]() |
d4cdb3ff83 | ||
![]() |
a7cac91e45 | ||
![]() |
6a6d72cd9a | ||
![]() |
11d74b3ea5 | ||
![]() |
5b65cf84eb | ||
![]() |
6b7af0474f | ||
![]() |
99f7e55044 | ||
![]() |
6b522b1c31 | ||
![]() |
0f35e48690 | ||
![]() |
53d19dd628 | ||
![]() |
155dc1bec8 | ||
![]() |
be26e39eae | ||
![]() |
90fa5ea8e8 | ||
![]() |
4845251f78 | ||
![]() |
31ef3fec58 |
@@ -56,6 +56,7 @@ blocks:
|
||||
- name: GDJS typing and documentation generation
|
||||
commands:
|
||||
- checkout
|
||||
- cache restore newIDE-app-node_modules-$SEMAPHORE_GIT_BRANCH-revision-$(checksum newIDE/app/package-lock.json)
|
||||
- cache restore GDJS-node_modules-$SEMAPHORE_GIT_BRANCH-revision-$(checksum GDJS/package-lock.json)
|
||||
- cache restore GDJS-tests-node_modules-$SEMAPHORE_GIT_BRANCH-revision-$(checksum GDJS/tests/package-lock.json)
|
||||
- cd GDJS
|
||||
|
1
.vscode/tasks.json
vendored
1
.vscode/tasks.json
vendored
@@ -8,6 +8,7 @@
|
||||
"group": "build",
|
||||
"label": "Start development server",
|
||||
"detail": "Starts the GDevelop development server.",
|
||||
"options": { "env": { "NODE_OPTIONS": "--max-old-space-size=8192" } },
|
||||
"problemMatcher": [
|
||||
{
|
||||
"owner": "cra",
|
||||
|
@@ -14,7 +14,8 @@ EventsBasedObject::EventsBasedObject()
|
||||
"MyObject",
|
||||
gd::EventsFunctionsContainer::FunctionOwner::Object),
|
||||
ObjectsContainer(),
|
||||
isRenderedIn3D(false) {
|
||||
isRenderedIn3D(false),
|
||||
isTextContainer(false) {
|
||||
}
|
||||
|
||||
EventsBasedObject::~EventsBasedObject() {}
|
||||
@@ -31,6 +32,9 @@ void EventsBasedObject::SerializeTo(SerializerElement& element) const {
|
||||
if (isRenderedIn3D) {
|
||||
element.SetBoolAttribute("is3D", true);
|
||||
}
|
||||
if (isTextContainer) {
|
||||
element.SetBoolAttribute("isTextContainer", true);
|
||||
}
|
||||
|
||||
AbstractEventsBasedEntity::SerializeTo(element);
|
||||
SerializeObjectsTo(element.AddChild("objects"));
|
||||
@@ -41,6 +45,7 @@ void EventsBasedObject::UnserializeFrom(gd::Project& project,
|
||||
const SerializerElement& element) {
|
||||
defaultName = element.GetStringAttribute("defaultName");
|
||||
isRenderedIn3D = element.GetBoolAttribute("is3D", false);
|
||||
isTextContainer = element.GetBoolAttribute("isTextContainer", false);
|
||||
|
||||
AbstractEventsBasedEntity::UnserializeFrom(project, element);
|
||||
UnserializeObjectsFrom(project, element.GetChild("objects"));
|
||||
|
@@ -85,6 +85,19 @@ class GD_CORE_API EventsBasedObject: public AbstractEventsBasedEntity, public Ob
|
||||
*/
|
||||
bool IsRenderedIn3D() const { return isRenderedIn3D; }
|
||||
|
||||
/**
|
||||
* \brief Declare a TextContainer capability.
|
||||
*/
|
||||
EventsBasedObject& MarkAsTextContainer(bool isTextContainer_) {
|
||||
isTextContainer = isTextContainer_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return true if the object needs a TextContainer capability.
|
||||
*/
|
||||
bool IsTextContainer() const { return isTextContainer; }
|
||||
|
||||
void SerializeTo(SerializerElement& element) const override;
|
||||
|
||||
void UnserializeFrom(gd::Project& project,
|
||||
@@ -93,6 +106,7 @@ class GD_CORE_API EventsBasedObject: public AbstractEventsBasedEntity, public Ob
|
||||
private:
|
||||
gd::String defaultName;
|
||||
bool isRenderedIn3D;
|
||||
bool isTextContainer;
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -102,30 +102,19 @@ std::unique_ptr<gd::Object> Project::CreateObject(
|
||||
behavior->SetDefaultBehavior(true);
|
||||
};
|
||||
|
||||
if (project.HasEventsBasedObject(objectType)) {
|
||||
// During project deserialization, event-based object metadata are not yet
|
||||
// generated.
|
||||
addDefaultBehavior("EffectCapability::EffectBehavior");
|
||||
addDefaultBehavior("ResizableCapability::ResizableBehavior");
|
||||
addDefaultBehavior("ScalableCapability::ScalableBehavior");
|
||||
addDefaultBehavior("FlippableCapability::FlippableBehavior");
|
||||
auto& eventBasedObject = project.GetEventsBasedObject(objectType);
|
||||
if (eventBasedObject.IsRenderedIn3D()) {
|
||||
addDefaultBehavior("Scene3D::Base3DBehavior");
|
||||
}
|
||||
else {
|
||||
addDefaultBehavior("OpacityCapability::OpacityBehavior");
|
||||
}
|
||||
} else {
|
||||
auto& objectMetadata =
|
||||
gd::MetadataProvider::GetObjectMetadata(platform, objectType);
|
||||
if (MetadataProvider::IsBadObjectMetadata(objectMetadata)) {
|
||||
gd::LogWarning("Object: " + name + " has an unknown type: " + objectType);
|
||||
}
|
||||
for (auto& behaviorType : objectMetadata.GetDefaultBehaviors()) {
|
||||
auto &objectMetadata =
|
||||
gd::MetadataProvider::GetObjectMetadata(platform, objectType);
|
||||
if (!MetadataProvider::IsBadObjectMetadata(objectMetadata)) {
|
||||
for (auto &behaviorType : objectMetadata.GetDefaultBehaviors()) {
|
||||
addDefaultBehavior(behaviorType);
|
||||
}
|
||||
}
|
||||
// During project deserialization, event-based object metadata are not yet
|
||||
// generated. Default behaviors will be added by
|
||||
// MetadataDeclarationHelper::UpdateCustomObjectDefaultBehaviors
|
||||
else if (!project.HasEventsBasedObject(objectType)) {
|
||||
gd::LogWarning("Object: " + name + " has an unknown type: " + objectType);
|
||||
}
|
||||
|
||||
return std::move(object);
|
||||
}
|
||||
|
@@ -105,7 +105,7 @@ namespace gdjs {
|
||||
if (this._isUntransformedHitBoxesDirty) {
|
||||
this._updateUntransformedHitBoxes();
|
||||
}
|
||||
return this._minZ;
|
||||
return this._z + this._minZ;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -80,7 +80,7 @@ namespace gdjs {
|
||||
|
||||
threeObject3D.visible = !this._object.hidden;
|
||||
|
||||
this._isContainerDirty = true;
|
||||
this._isContainerDirty = false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -1,4 +1,5 @@
|
||||
// @flow
|
||||
//@ts-check
|
||||
/// <reference path="../JsExtensionTypes.d.ts" />
|
||||
/**
|
||||
* This is a declaration of an extension for GDevelop 5.
|
||||
*
|
||||
@@ -12,18 +13,9 @@
|
||||
* More information on https://github.com/4ian/GDevelop/blob/master/newIDE/README-extensions.md
|
||||
*/
|
||||
|
||||
/*::
|
||||
// Import types to allow Flow to do static type checking on this file.
|
||||
// Extensions declaration are typed using Flow (like the editor), but the files
|
||||
// for the game engine are checked with TypeScript annotations.
|
||||
import { type ObjectsRenderingService, type ObjectsEditorService } from '../JsExtensionTypes.flow.js'
|
||||
*/
|
||||
|
||||
/** @type {ExtensionModule} */
|
||||
module.exports = {
|
||||
createExtension: function (
|
||||
_ /*: (string) => string */,
|
||||
gd /*: libGDevelop */
|
||||
) {
|
||||
createExtension: function (_, gd) {
|
||||
const extension = new gd.PlatformExtension();
|
||||
extension
|
||||
.setExtensionInformation(
|
||||
@@ -811,7 +803,6 @@ module.exports = {
|
||||
}
|
||||
|
||||
const Cube3DObject = new gd.ObjectJsImplementation();
|
||||
// $FlowExpectedError - ignore Flow warning as we're creating an object
|
||||
Cube3DObject.updateProperty = function (
|
||||
objectContent,
|
||||
propertyName,
|
||||
@@ -860,7 +851,6 @@ module.exports = {
|
||||
|
||||
return false;
|
||||
};
|
||||
// $FlowExpectedError - ignore Flow warning as we're creating an object
|
||||
Cube3DObject.getProperties = function (objectContent) {
|
||||
const objectProperties = new gd.MapStringPropertyDescriptor();
|
||||
|
||||
@@ -1100,7 +1090,6 @@ module.exports = {
|
||||
})
|
||||
);
|
||||
|
||||
// $FlowExpectedError
|
||||
Cube3DObject.updateInitialInstanceProperty = function (
|
||||
objectContent,
|
||||
instance,
|
||||
@@ -1112,7 +1101,6 @@ module.exports = {
|
||||
return false;
|
||||
};
|
||||
|
||||
// $FlowExpectedError
|
||||
Cube3DObject.getInitialInstanceProperties = function (
|
||||
content,
|
||||
instance,
|
||||
@@ -1665,7 +1653,7 @@ module.exports = {
|
||||
'Change the camera rotation to look at an object. The camera top always face the screen.'
|
||||
),
|
||||
_('Change the camera rotation of _PARAM2_ to look at _PARAM1_'),
|
||||
_("Layers and cameras"),
|
||||
_('Layers and cameras'),
|
||||
'res/conditions/3d_box.svg',
|
||||
'res/conditions/3d_box.svg'
|
||||
)
|
||||
@@ -1943,11 +1931,7 @@ module.exports = {
|
||||
const effect = extension
|
||||
.addEffect('HueAndSaturation')
|
||||
.setFullName(_('Hue and saturation'))
|
||||
.setDescription(
|
||||
_(
|
||||
'Adjust hue and saturation.'
|
||||
)
|
||||
)
|
||||
.setDescription(_('Adjust hue and saturation.'))
|
||||
.markAsNotWorkingForObjects()
|
||||
.markAsOnlyWorkingFor3D()
|
||||
.addIncludeFile('Extensions/3D/HueAndSaturationEffect.js');
|
||||
@@ -1967,11 +1951,7 @@ module.exports = {
|
||||
const effect = extension
|
||||
.addEffect('Exposure')
|
||||
.setFullName(_('Exposure'))
|
||||
.setDescription(
|
||||
_(
|
||||
'Adjust exposure.'
|
||||
)
|
||||
)
|
||||
.setDescription(_('Adjust exposure.'))
|
||||
.markAsNotWorkingForObjects()
|
||||
.markAsOnlyWorkingFor3D()
|
||||
.addIncludeFile('Extensions/3D/ExposureEffect.js');
|
||||
@@ -1986,11 +1966,7 @@ module.exports = {
|
||||
const effect = extension
|
||||
.addEffect('Bloom')
|
||||
.setFullName(_('Bloom'))
|
||||
.setDescription(
|
||||
_(
|
||||
'Apply a bloom effect.'
|
||||
)
|
||||
)
|
||||
.setDescription(_('Apply a bloom effect.'))
|
||||
.markAsNotWorkingForObjects()
|
||||
.markAsOnlyWorkingFor3D()
|
||||
.addIncludeFile('Extensions/3D/BloomEffect.js');
|
||||
@@ -2014,12 +1990,8 @@ module.exports = {
|
||||
{
|
||||
const effect = extension
|
||||
.addEffect('BrightnessAndContrast')
|
||||
.setFullName(_('Brightness and contrast'))
|
||||
.setDescription(
|
||||
_(
|
||||
'Adjust brightness and contrast.'
|
||||
)
|
||||
)
|
||||
.setFullName(_('Brightness and contrast.'))
|
||||
.setDescription(_('Adjust brightness and contrast.'))
|
||||
.markAsNotWorkingForObjects()
|
||||
.markAsOnlyWorkingFor3D()
|
||||
.addIncludeFile('Extensions/3D/BrightnessAndContrastEffect.js');
|
||||
@@ -2050,10 +2022,7 @@ module.exports = {
|
||||
* But it is recommended to create tests for the behaviors/objects properties you created
|
||||
* to avoid mistakes.
|
||||
*/
|
||||
runExtensionSanityTests: function (
|
||||
gd /*: libGDevelop */,
|
||||
extension /*: gdPlatformExtension*/
|
||||
) {
|
||||
runExtensionSanityTests: function (gd, extension) {
|
||||
return [];
|
||||
},
|
||||
/**
|
||||
@@ -2061,17 +2030,13 @@ module.exports = {
|
||||
*
|
||||
* ℹ️ Run `node import-GDJS-Runtime.js` (in newIDE/app/scripts) if you make any change.
|
||||
*/
|
||||
registerEditorConfigurations: function (
|
||||
objectsEditorService /*: ObjectsEditorService */
|
||||
) {},
|
||||
registerEditorConfigurations: function (objectsEditorService) {},
|
||||
/**
|
||||
* Register renderers for instance of objects on the scene editor.
|
||||
*
|
||||
* ℹ️ Run `node import-GDJS-Runtime.js` (in newIDE/app/scripts) if you make any change.
|
||||
*/
|
||||
registerInstanceRenderers: function (
|
||||
objectsRenderingService /*: ObjectsRenderingService */
|
||||
) {
|
||||
registerInstanceRenderers: function (objectsRenderingService) {
|
||||
const RenderedInstance = objectsRenderingService.RenderedInstance;
|
||||
const Rendered3DInstance = objectsRenderingService.Rendered3DInstance;
|
||||
const PIXI = objectsRenderingService.PIXI;
|
||||
@@ -2079,39 +2044,25 @@ module.exports = {
|
||||
const THREE_ADDONS = objectsRenderingService.THREE_ADDONS;
|
||||
|
||||
const materialIndexToFaceIndex = {
|
||||
// $FlowFixMe
|
||||
0: 3,
|
||||
// $FlowFixMe
|
||||
1: 2,
|
||||
// $FlowFixMe
|
||||
2: 5,
|
||||
// $FlowFixMe
|
||||
3: 4,
|
||||
// $FlowFixMe
|
||||
4: 0,
|
||||
// $FlowFixMe
|
||||
5: 1,
|
||||
};
|
||||
|
||||
const noRepeatTextureVertexIndexToUvMapping = {
|
||||
// $FlowFixMe
|
||||
0: [0, 0],
|
||||
// $FlowFixMe
|
||||
1: [1, 0],
|
||||
// $FlowFixMe
|
||||
2: [0, 1],
|
||||
// $FlowFixMe
|
||||
3: [1, 1],
|
||||
};
|
||||
|
||||
const noRepeatTextureVertexIndexToUvMappingForLeftAndRightFacesTowardsZ = {
|
||||
// $FlowFixMe
|
||||
0: [0, 1],
|
||||
// $FlowFixMe
|
||||
1: [0, 0],
|
||||
// $FlowFixMe
|
||||
2: [1, 1],
|
||||
// $FlowFixMe
|
||||
3: [1, 0],
|
||||
};
|
||||
|
||||
@@ -2157,6 +2108,11 @@ module.exports = {
|
||||
};
|
||||
|
||||
class RenderedCube3DObject2DInstance extends RenderedInstance {
|
||||
/** @type {number} */
|
||||
_centerX = 0;
|
||||
/** @type {number} */
|
||||
_centerY = 0;
|
||||
|
||||
constructor(
|
||||
project,
|
||||
layout,
|
||||
@@ -2173,10 +2129,9 @@ module.exports = {
|
||||
pixiContainer,
|
||||
pixiResourcesLoader
|
||||
);
|
||||
/**
|
||||
* Name of the resource that is rendered.
|
||||
* If no face is visible, this will be null.
|
||||
*/
|
||||
|
||||
// Name of the resource that is rendered.
|
||||
// If no face is visible, this will be null.
|
||||
this._renderedResourceName = undefined;
|
||||
const properties = associatedObjectConfiguration.getProperties();
|
||||
this._defaultWidth = parseFloat(properties.get('width').getValue());
|
||||
@@ -2206,12 +2161,9 @@ module.exports = {
|
||||
}
|
||||
|
||||
static getThumbnail(project, resourcesLoader, objectConfiguration) {
|
||||
const instance = this._instance;
|
||||
|
||||
const textureResourceName =
|
||||
RenderedCube3DObject2DInstance._getResourceNameToDisplay(
|
||||
objectConfiguration
|
||||
);
|
||||
const textureResourceName = RenderedCube3DObject2DInstance._getResourceNameToDisplay(
|
||||
objectConfiguration
|
||||
);
|
||||
if (textureResourceName) {
|
||||
return resourcesLoader.getResourceFullUrl(
|
||||
project,
|
||||
@@ -2223,20 +2175,18 @@ module.exports = {
|
||||
}
|
||||
|
||||
updateTextureIfNeeded() {
|
||||
const textureName =
|
||||
RenderedCube3DObject2DInstance._getResourceNameToDisplay(
|
||||
this._associatedObjectConfiguration
|
||||
);
|
||||
const textureName = RenderedCube3DObject2DInstance._getResourceNameToDisplay(
|
||||
this._associatedObjectConfiguration
|
||||
);
|
||||
if (textureName === this._renderedResourceName) return;
|
||||
|
||||
this.updateTexture();
|
||||
}
|
||||
|
||||
updateTexture() {
|
||||
const textureName =
|
||||
RenderedCube3DObject2DInstance._getResourceNameToDisplay(
|
||||
this._associatedObjectConfiguration
|
||||
);
|
||||
const textureName = RenderedCube3DObject2DInstance._getResourceNameToDisplay(
|
||||
this._associatedObjectConfiguration
|
||||
);
|
||||
|
||||
if (!textureName) {
|
||||
this._renderFallbackObject = true;
|
||||
@@ -2494,10 +2444,9 @@ module.exports = {
|
||||
continue;
|
||||
}
|
||||
|
||||
const shouldRepeatTexture =
|
||||
this._shouldRepeatTextureOnFace[
|
||||
materialIndexToFaceIndex[materialIndex]
|
||||
];
|
||||
const shouldRepeatTexture = this._shouldRepeatTextureOnFace[
|
||||
materialIndexToFaceIndex[materialIndex]
|
||||
];
|
||||
|
||||
const shouldOrientateFacesTowardsY = this._facesOrientation === 'Y';
|
||||
|
||||
@@ -2532,13 +2481,16 @@ module.exports = {
|
||||
}
|
||||
} else {
|
||||
if (shouldOrientateFacesTowardsY) {
|
||||
[x, y] =
|
||||
noRepeatTextureVertexIndexToUvMapping[vertexIndex % 4];
|
||||
[x, y] = noRepeatTextureVertexIndexToUvMapping[
|
||||
vertexIndex % 4
|
||||
];
|
||||
} else {
|
||||
[x, y] =
|
||||
noRepeatTextureVertexIndexToUvMappingForLeftAndRightFacesTowardsZ[
|
||||
vertexIndex % 4
|
||||
];
|
||||
[
|
||||
x,
|
||||
y,
|
||||
] = noRepeatTextureVertexIndexToUvMappingForLeftAndRightFacesTowardsZ[
|
||||
vertexIndex % 4
|
||||
];
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -2568,13 +2520,16 @@ module.exports = {
|
||||
}
|
||||
} else {
|
||||
if (shouldOrientateFacesTowardsY) {
|
||||
[x, y] =
|
||||
noRepeatTextureVertexIndexToUvMapping[vertexIndex % 4];
|
||||
[x, y] = noRepeatTextureVertexIndexToUvMapping[
|
||||
vertexIndex % 4
|
||||
];
|
||||
} else {
|
||||
[x, y] =
|
||||
noRepeatTextureVertexIndexToUvMappingForLeftAndRightFacesTowardsZ[
|
||||
vertexIndex % 4
|
||||
];
|
||||
[
|
||||
x,
|
||||
y,
|
||||
] = noRepeatTextureVertexIndexToUvMappingForLeftAndRightFacesTowardsZ[
|
||||
vertexIndex % 4
|
||||
];
|
||||
x = -x;
|
||||
y = -y;
|
||||
}
|
||||
@@ -3111,7 +3066,7 @@ module.exports = {
|
||||
);
|
||||
threeObject.updateMatrixWorld(true);
|
||||
const boundingBox = new THREE.Box3().setFromObject(threeObject);
|
||||
|
||||
|
||||
const shouldKeepModelOrigin = !this._originPoint;
|
||||
if (shouldKeepModelOrigin) {
|
||||
// Keep the origin as part of the model.
|
||||
|
@@ -1,4 +1,5 @@
|
||||
// @flow
|
||||
//@ts-check
|
||||
/// <reference path="../JsExtensionTypes.d.ts" />
|
||||
/**
|
||||
* This is a declaration of an extension for GDevelop 5.
|
||||
*
|
||||
@@ -12,18 +13,9 @@
|
||||
* More information on https://github.com/4ian/GDevelop/blob/master/newIDE/README-extensions.md
|
||||
*/
|
||||
|
||||
/*::
|
||||
// Import types to allow Flow to do static type checking on this file.
|
||||
// Extensions declaration are typed using Flow (like the editor), but the files
|
||||
// for the game engine are checked with TypeScript annotations.
|
||||
import { type ObjectsRenderingService, type ObjectsEditorService } from '../JsExtensionTypes.flow.js'
|
||||
*/
|
||||
|
||||
/** @type {ExtensionModule} */
|
||||
module.exports = {
|
||||
createExtension: function (
|
||||
_ /*: (string) => string */,
|
||||
gd /*: libGDevelop */
|
||||
) {
|
||||
createExtension: function (_, gd) {
|
||||
const extension = new gd.PlatformExtension();
|
||||
extension
|
||||
.setExtensionInformation(
|
||||
@@ -789,10 +781,7 @@ module.exports = {
|
||||
|
||||
return extension;
|
||||
},
|
||||
runExtensionSanityTests: function (
|
||||
gd /*: libGDevelop */,
|
||||
extension /*: gdPlatformExtension*/
|
||||
) {
|
||||
runExtensionSanityTests: function (gd, extension) {
|
||||
return [];
|
||||
},
|
||||
};
|
||||
|
@@ -1,4 +1,5 @@
|
||||
// @flow
|
||||
//@ts-check
|
||||
/// <reference path="../JsExtensionTypes.d.ts" />
|
||||
/**
|
||||
* This is a declaration of an extension for GDevelop 5.
|
||||
*
|
||||
@@ -12,11 +13,9 @@
|
||||
* More information on https://github.com/4ian/GDevelop/blob/master/newIDE/README-extensions.md
|
||||
*/
|
||||
|
||||
/** @type {ExtensionModule} */
|
||||
module.exports = {
|
||||
createExtension: function (
|
||||
_ /*: (string) => string */,
|
||||
gd /*: libGDevelop */
|
||||
) {
|
||||
createExtension: function (_, gd) {
|
||||
const extension = new gd.PlatformExtension();
|
||||
extension
|
||||
.setExtensionInformation(
|
||||
@@ -710,10 +709,7 @@ module.exports = {
|
||||
|
||||
return extension;
|
||||
},
|
||||
runExtensionSanityTests: function (
|
||||
gd /*: libGDevelop */,
|
||||
extension /*: gdPlatformExtension*/
|
||||
) {
|
||||
runExtensionSanityTests: function (gd, extension) {
|
||||
return [];
|
||||
},
|
||||
};
|
||||
|
@@ -1,4 +1,5 @@
|
||||
// @flow
|
||||
//@ts-check
|
||||
/// <reference path="../JsExtensionTypes.d.ts" />
|
||||
/**
|
||||
* This is a declaration of an extension for GDevelop 5.
|
||||
*
|
||||
@@ -12,20 +13,11 @@
|
||||
* More information on https://github.com/4ian/GDevelop/blob/master/newIDE/README-extensions.md
|
||||
*/
|
||||
|
||||
/*::
|
||||
// Import types to allow Flow to do static type checking on this file.
|
||||
// Extensions declaration are typed using Flow (like the editor), but the files
|
||||
// for the game engine are checked with TypeScript annotations.
|
||||
import { type ObjectsRenderingService, type ObjectsEditorService } from '../JsExtensionTypes.flow.js'
|
||||
*/
|
||||
|
||||
const stringifyOptions = (options) => '["' + options.join('","') + '"]';
|
||||
|
||||
/** @type {ExtensionModule} */
|
||||
module.exports = {
|
||||
createExtension: function (
|
||||
_ /*: (string) => string */,
|
||||
gd /*: libGDevelop */
|
||||
) {
|
||||
createExtension: function (_, gd) {
|
||||
const extension = new gd.PlatformExtension();
|
||||
extension
|
||||
.setExtensionInformation(
|
||||
@@ -42,7 +34,6 @@ module.exports = {
|
||||
.setIcon('JsPlatform/Extensions/bbcode32.png');
|
||||
|
||||
var objectBBText = new gd.ObjectJsImplementation();
|
||||
// $FlowExpectedError
|
||||
objectBBText.updateProperty = function (
|
||||
objectContent,
|
||||
propertyName,
|
||||
@@ -59,7 +50,6 @@ module.exports = {
|
||||
|
||||
return false;
|
||||
};
|
||||
// $FlowExpectedError
|
||||
objectBBText.getProperties = function (objectContent) {
|
||||
const objectProperties = new gd.MapStringPropertyDescriptor();
|
||||
|
||||
@@ -126,7 +116,8 @@ module.exports = {
|
||||
};
|
||||
objectBBText.setRawJSONContent(
|
||||
JSON.stringify({
|
||||
text: '[b]bold[/b] [i]italic[/i] [size=15]smaller[/size] [font=times]times[/font] font\n[spacing=12]spaced out[/spacing]\n[outline=yellow]outlined[/outline] [shadow=red]DropShadow[/shadow] ',
|
||||
text:
|
||||
'[b]bold[/b] [i]italic[/i] [size=15]smaller[/size] [font=times]times[/font] font\n[spacing=12]spaced out[/spacing]\n[outline=yellow]outlined[/outline] [shadow=red]DropShadow[/shadow] ',
|
||||
opacity: 255,
|
||||
fontSize: 20,
|
||||
visible: true,
|
||||
@@ -137,7 +128,6 @@ module.exports = {
|
||||
})
|
||||
);
|
||||
|
||||
// $FlowExpectedError
|
||||
objectBBText.updateInitialInstanceProperty = function (
|
||||
objectContent,
|
||||
instance,
|
||||
@@ -148,7 +138,6 @@ module.exports = {
|
||||
) {
|
||||
return false;
|
||||
};
|
||||
// $FlowExpectedError
|
||||
objectBBText.getInitialInstanceProperties = function (
|
||||
content,
|
||||
instance,
|
||||
@@ -223,10 +212,9 @@ module.exports = {
|
||||
parameterType === 'string' ||
|
||||
parameterType === 'stringWithSelector'
|
||||
) {
|
||||
const parameterOptions =
|
||||
gd.ParameterOptions.makeNewOptions().setDescription(
|
||||
property.paramLabel
|
||||
);
|
||||
const parameterOptions = gd.ParameterOptions.makeNewOptions().setDescription(
|
||||
property.paramLabel
|
||||
);
|
||||
if (property.options) {
|
||||
parameterOptions.setTypeExtraInfo(
|
||||
stringifyOptions(property.options)
|
||||
@@ -276,10 +264,9 @@ module.exports = {
|
||||
parameterType === 'number' ||
|
||||
parameterType === 'stringWithSelector'
|
||||
) {
|
||||
const parameterOptions =
|
||||
gd.ParameterOptions.makeNewOptions().setDescription(
|
||||
property.paramLabel
|
||||
);
|
||||
const parameterOptions = gd.ParameterOptions.makeNewOptions().setDescription(
|
||||
property.paramLabel
|
||||
);
|
||||
if (property.options) {
|
||||
parameterOptions.setTypeExtraInfo(
|
||||
stringifyOptions(property.options)
|
||||
@@ -475,10 +462,7 @@ module.exports = {
|
||||
* But it is recommended to create tests for the behaviors/objects properties you created
|
||||
* to avoid mistakes.
|
||||
*/
|
||||
runExtensionSanityTests: function (
|
||||
gd /*: libGDevelop */,
|
||||
extension /*: gdPlatformExtension*/
|
||||
) {
|
||||
runExtensionSanityTests: function (gd, extension) {
|
||||
return [];
|
||||
},
|
||||
/**
|
||||
@@ -486,9 +470,7 @@ module.exports = {
|
||||
*
|
||||
* ℹ️ Run `node import-GDJS-Runtime.js` (in newIDE/app/scripts) if you make any change.
|
||||
*/
|
||||
registerEditorConfigurations: function (
|
||||
objectsEditorService /*: ObjectsEditorService */
|
||||
) {
|
||||
registerEditorConfigurations: function (objectsEditorService) {
|
||||
objectsEditorService.registerEditorConfiguration(
|
||||
'BBText::BBText',
|
||||
objectsEditorService.getDefaultObjectJsImplementationPropertiesEditor({
|
||||
@@ -501,11 +483,8 @@ module.exports = {
|
||||
*
|
||||
* ℹ️ Run `node import-GDJS-Runtime.js` (in newIDE/app/scripts) if you make any change.
|
||||
*/
|
||||
registerInstanceRenderers: function (
|
||||
objectsRenderingService /*: ObjectsRenderingService */
|
||||
) {
|
||||
registerInstanceRenderers: function (objectsRenderingService) {
|
||||
const RenderedInstance = objectsRenderingService.RenderedInstance;
|
||||
const PIXI = objectsRenderingService.PIXI;
|
||||
const MultiStyleText = objectsRenderingService.requireModule(
|
||||
__dirname,
|
||||
'pixi-multistyle-text/dist/pixi-multistyle-text.umd'
|
||||
@@ -514,150 +493,145 @@ module.exports = {
|
||||
/**
|
||||
* Renderer for instances of BBText inside the IDE.
|
||||
*
|
||||
* @extends RenderedBBTextInstance
|
||||
* @extends RenderedInstance
|
||||
* @class RenderedBBTextInstance
|
||||
* @constructor
|
||||
*/
|
||||
function RenderedBBTextInstance(
|
||||
project,
|
||||
layout,
|
||||
instance,
|
||||
associatedObjectConfiguration,
|
||||
pixiContainer,
|
||||
pixiResourcesLoader
|
||||
) {
|
||||
RenderedInstance.call(
|
||||
this,
|
||||
class RenderedBBTextInstance extends RenderedInstance {
|
||||
constructor(
|
||||
project,
|
||||
layout,
|
||||
instance,
|
||||
associatedObjectConfiguration,
|
||||
pixiContainer,
|
||||
pixiResourcesLoader
|
||||
);
|
||||
) {
|
||||
super(
|
||||
project,
|
||||
layout,
|
||||
instance,
|
||||
associatedObjectConfiguration,
|
||||
pixiContainer,
|
||||
pixiResourcesLoader
|
||||
);
|
||||
|
||||
const bbTextStyles = {
|
||||
default: {
|
||||
// Use a default font family the time for the resource font to be loaded.
|
||||
fontFamily: 'Arial',
|
||||
fontSize: '24px',
|
||||
fill: '#cccccc',
|
||||
tagStyle: 'bbcode',
|
||||
wordWrap: true,
|
||||
wordWrapWidth: 250, // This value is the default wrapping width of the runtime object.
|
||||
align: 'left',
|
||||
},
|
||||
};
|
||||
const bbTextStyles = {
|
||||
default: {
|
||||
// Use a default font family the time for the resource font to be loaded.
|
||||
fontFamily: 'Arial',
|
||||
fontSize: '24px',
|
||||
fill: '#cccccc',
|
||||
tagStyle: 'bbcode',
|
||||
wordWrap: true,
|
||||
wordWrapWidth: 250, // This value is the default wrapping width of the runtime object.
|
||||
align: 'left',
|
||||
},
|
||||
};
|
||||
|
||||
this._pixiObject = new MultiStyleText('', bbTextStyles);
|
||||
this._pixiObject = new MultiStyleText('', bbTextStyles);
|
||||
|
||||
this._pixiObject.anchor.x = 0.5;
|
||||
this._pixiObject.anchor.y = 0.5;
|
||||
this._pixiContainer.addChild(this._pixiObject);
|
||||
this.update();
|
||||
}
|
||||
RenderedBBTextInstance.prototype = Object.create(
|
||||
RenderedInstance.prototype
|
||||
);
|
||||
|
||||
/**
|
||||
* Return the path to the thumbnail of the specified object.
|
||||
*/
|
||||
RenderedBBTextInstance.getThumbnail = function (
|
||||
project,
|
||||
resourcesLoader,
|
||||
objectConfiguration
|
||||
) {
|
||||
return 'JsPlatform/Extensions/bbcode24.png';
|
||||
};
|
||||
|
||||
/**
|
||||
* This is called to update the PIXI object on the scene editor
|
||||
*/
|
||||
RenderedBBTextInstance.prototype.update = function () {
|
||||
const properties = this._associatedObjectConfiguration.getProperties();
|
||||
|
||||
const rawText = properties.get('text').getValue();
|
||||
if (rawText !== this._pixiObject.text) {
|
||||
this._pixiObject.text = rawText;
|
||||
this._pixiObject.anchor.x = 0.5;
|
||||
this._pixiObject.anchor.y = 0.5;
|
||||
this._pixiContainer.addChild(this._pixiObject);
|
||||
this.update();
|
||||
}
|
||||
|
||||
const opacity = properties.get('opacity').getValue();
|
||||
this._pixiObject.alpha = opacity / 255;
|
||||
|
||||
const color = properties.get('color').getValue();
|
||||
this._pixiObject.textStyles.default.fill =
|
||||
objectsRenderingService.rgbOrHexToHexNumber(color);
|
||||
|
||||
const fontSize = properties.get('fontSize').getValue();
|
||||
this._pixiObject.textStyles.default.fontSize = `${fontSize}px`;
|
||||
|
||||
const fontResourceName = properties.get('fontFamily').getValue();
|
||||
|
||||
if (this._fontResourceName !== fontResourceName) {
|
||||
this._fontResourceName = fontResourceName;
|
||||
|
||||
this._pixiResourcesLoader
|
||||
.loadFontFamily(this._project, fontResourceName)
|
||||
.then((fontFamily) => {
|
||||
// Once the font is loaded, we can use the given fontFamily.
|
||||
this._pixiObject.textStyles.default.fontFamily = fontFamily;
|
||||
this._pixiObject.dirty = true;
|
||||
})
|
||||
.catch((err) => {
|
||||
// Ignore errors
|
||||
console.warn(
|
||||
'Unable to load font family for RenderedBBTextInstance',
|
||||
err
|
||||
);
|
||||
});
|
||||
/**
|
||||
* Return the path to the thumbnail of the specified object.
|
||||
*/
|
||||
static getThumbnail(project, resourcesLoader, objectConfiguration) {
|
||||
return 'JsPlatform/Extensions/bbcode24.png';
|
||||
}
|
||||
|
||||
const wordWrap = properties.get('wordWrap').getValue() === 'true';
|
||||
if (wordWrap !== this._pixiObject._style.wordWrap) {
|
||||
this._pixiObject._style.wordWrap = wordWrap;
|
||||
this._pixiObject.dirty = true;
|
||||
}
|
||||
/**
|
||||
* This is called to update the PIXI object on the scene editor
|
||||
*/
|
||||
update() {
|
||||
const properties = this._associatedObjectConfiguration.getProperties();
|
||||
|
||||
const align = properties.get('align').getValue();
|
||||
if (align !== this._pixiObject._style.align) {
|
||||
this._pixiObject._style.align = align;
|
||||
this._pixiObject.dirty = true;
|
||||
}
|
||||
const rawText = properties.get('text').getValue();
|
||||
if (rawText !== this._pixiObject.text) {
|
||||
this._pixiObject.text = rawText;
|
||||
}
|
||||
|
||||
this._pixiObject.position.x =
|
||||
this._instance.getX() + this._pixiObject.width / 2;
|
||||
this._pixiObject.position.y =
|
||||
this._instance.getY() + this._pixiObject.height / 2;
|
||||
this._pixiObject.rotation = RenderedInstance.toRad(
|
||||
this._instance.getAngle()
|
||||
);
|
||||
const opacity = +properties.get('opacity').getValue();
|
||||
this._pixiObject.alpha = opacity / 255;
|
||||
|
||||
if (this._instance.hasCustomSize() && this._pixiObject) {
|
||||
const customWidth = this.getCustomWidth();
|
||||
if (
|
||||
this._pixiObject &&
|
||||
this._pixiObject._style.wordWrapWidth !== customWidth
|
||||
) {
|
||||
this._pixiObject._style.wordWrapWidth = customWidth;
|
||||
const color = properties.get('color').getValue();
|
||||
this._pixiObject.textStyles.default.fill = objectsRenderingService.rgbOrHexToHexNumber(
|
||||
color
|
||||
);
|
||||
|
||||
const fontSize = properties.get('fontSize').getValue();
|
||||
this._pixiObject.textStyles.default.fontSize = `${fontSize}px`;
|
||||
|
||||
const fontResourceName = properties.get('fontFamily').getValue();
|
||||
|
||||
if (this._fontResourceName !== fontResourceName) {
|
||||
this._fontResourceName = fontResourceName;
|
||||
|
||||
this._pixiResourcesLoader
|
||||
.loadFontFamily(this._project, fontResourceName)
|
||||
.then((fontFamily) => {
|
||||
// Once the font is loaded, we can use the given fontFamily.
|
||||
this._pixiObject.textStyles.default.fontFamily = fontFamily;
|
||||
this._pixiObject.dirty = true;
|
||||
})
|
||||
.catch((err) => {
|
||||
// Ignore errors
|
||||
console.warn(
|
||||
'Unable to load font family for RenderedBBTextInstance',
|
||||
err
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
const wordWrap = properties.get('wordWrap').getValue() === 'true';
|
||||
if (wordWrap !== this._pixiObject._style.wordWrap) {
|
||||
this._pixiObject._style.wordWrap = wordWrap;
|
||||
this._pixiObject.dirty = true;
|
||||
}
|
||||
|
||||
const align = properties.get('align').getValue();
|
||||
if (align !== this._pixiObject._style.align) {
|
||||
this._pixiObject._style.align = align;
|
||||
this._pixiObject.dirty = true;
|
||||
}
|
||||
|
||||
this._pixiObject.position.x =
|
||||
this._instance.getX() + this._pixiObject.width / 2;
|
||||
this._pixiObject.position.y =
|
||||
this._instance.getY() + this._pixiObject.height / 2;
|
||||
this._pixiObject.rotation = RenderedInstance.toRad(
|
||||
this._instance.getAngle()
|
||||
);
|
||||
|
||||
if (this._instance.hasCustomSize() && this._pixiObject) {
|
||||
const customWidth = this.getCustomWidth();
|
||||
if (
|
||||
this._pixiObject &&
|
||||
this._pixiObject._style.wordWrapWidth !== customWidth
|
||||
) {
|
||||
this._pixiObject._style.wordWrapWidth = customWidth;
|
||||
this._pixiObject.dirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the width of the instance, when it's not resized.
|
||||
*/
|
||||
RenderedBBTextInstance.prototype.getDefaultWidth = function () {
|
||||
return this._pixiObject.width;
|
||||
};
|
||||
/**
|
||||
* Return the width of the instance, when it's not resized.
|
||||
*/
|
||||
getDefaultWidth() {
|
||||
return this._pixiObject.width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the height of the instance, when it's not resized.
|
||||
*/
|
||||
RenderedBBTextInstance.prototype.getDefaultHeight = function () {
|
||||
return this._pixiObject.height;
|
||||
};
|
||||
/**
|
||||
* Return the height of the instance, when it's not resized.
|
||||
*/
|
||||
getDefaultHeight() {
|
||||
return this._pixiObject.height;
|
||||
}
|
||||
}
|
||||
|
||||
objectsRenderingService.registerInstanceRenderer(
|
||||
'BBText::BBText',
|
||||
|
@@ -1,4 +1,5 @@
|
||||
// @flow
|
||||
//@ts-check
|
||||
/// <reference path="../JsExtensionTypes.d.ts" />
|
||||
/**
|
||||
* This is a declaration of an extension for GDevelop 5.
|
||||
*
|
||||
@@ -12,18 +13,9 @@
|
||||
* More information on https://github.com/4ian/GDevelop/blob/master/newIDE/README-extensions.md
|
||||
*/
|
||||
|
||||
/*::
|
||||
// Import types to allow Flow to do static type checking on this file.
|
||||
// Extensions declaration are typed using Flow (like the editor), but the files
|
||||
// for the game engine are checked with TypeScript annotations.
|
||||
import { type ObjectsRenderingService, type ObjectsEditorService } from '../JsExtensionTypes.flow.js'
|
||||
*/
|
||||
|
||||
/** @type {ExtensionModule} */
|
||||
module.exports = {
|
||||
createExtension: function (
|
||||
_ /*: (string) => string */,
|
||||
gd /*: libGDevelop */
|
||||
) {
|
||||
createExtension: function (_, gd) {
|
||||
const extension = new gd.PlatformExtension();
|
||||
extension
|
||||
.setExtensionInformation(
|
||||
@@ -42,7 +34,6 @@ module.exports = {
|
||||
.setIcon('JsPlatform/Extensions/bitmapfont32.png');
|
||||
|
||||
const bitmapTextObject = new gd.ObjectJsImplementation();
|
||||
// $FlowExpectedError
|
||||
bitmapTextObject.updateProperty = function (
|
||||
objectContent,
|
||||
propertyName,
|
||||
@@ -59,7 +50,6 @@ module.exports = {
|
||||
|
||||
return false;
|
||||
};
|
||||
// $FlowExpectedError
|
||||
bitmapTextObject.getProperties = function (objectContent) {
|
||||
const objectProperties = new gd.MapStringPropertyDescriptor();
|
||||
|
||||
@@ -127,7 +117,8 @@ module.exports = {
|
||||
};
|
||||
bitmapTextObject.setRawJSONContent(
|
||||
JSON.stringify({
|
||||
text: 'This text use the default bitmap font.\nUse a custom Bitmap Font to create your own texts.',
|
||||
text:
|
||||
'This text use the default bitmap font.\nUse a custom Bitmap Font to create your own texts.',
|
||||
opacity: 255,
|
||||
scale: 1,
|
||||
fontSize: 20,
|
||||
@@ -139,7 +130,6 @@ module.exports = {
|
||||
})
|
||||
);
|
||||
|
||||
// $FlowExpectedError
|
||||
bitmapTextObject.updateInitialInstanceProperty = function (
|
||||
objectContent,
|
||||
instance,
|
||||
@@ -150,7 +140,6 @@ module.exports = {
|
||||
) {
|
||||
return false;
|
||||
};
|
||||
// $FlowExpectedError
|
||||
bitmapTextObject.getInitialInstanceProperties = function (
|
||||
content,
|
||||
instance,
|
||||
@@ -176,7 +165,7 @@ module.exports = {
|
||||
'Extensions/BitmapText/bitmaptextruntimeobject-pixi-renderer.js'
|
||||
)
|
||||
.setCategoryFullName(_('Text'))
|
||||
.addDefaultBehavior("TextContainerCapability::TextContainerBehavior")
|
||||
.addDefaultBehavior('TextContainerCapability::TextContainerBehavior')
|
||||
.addDefaultBehavior('EffectCapability::EffectBehavior')
|
||||
.addDefaultBehavior('OpacityCapability::OpacityBehavior')
|
||||
.addDefaultBehavior('ScalableCapability::ScalableBehavior');
|
||||
@@ -327,33 +316,33 @@ module.exports = {
|
||||
.getCodeExtraInformation()
|
||||
.setFunctionName('setBitmapFontAndTextureAtlasResourceName');
|
||||
|
||||
object
|
||||
.addAction(
|
||||
'SetBitmapFontAndTextureAtlasResourceName2',
|
||||
_('Bitmap files resources'),
|
||||
_('Change the Bitmap Font and/or the atlas image used by the object.'),
|
||||
_(
|
||||
'Set the bitmap font of _PARAM0_ to _PARAM1_ and the atlas to _PARAM2_'
|
||||
),
|
||||
'',
|
||||
'res/actions/font24.png',
|
||||
'res/actions/font.png'
|
||||
)
|
||||
.addParameter('object', _('Bitmap text'), 'BitmapTextObject', false)
|
||||
.addParameter(
|
||||
'bitmapFontResource',
|
||||
_('Bitmap font resource name'),
|
||||
'',
|
||||
false
|
||||
)
|
||||
.addParameter(
|
||||
'imageResource',
|
||||
_('Texture atlas resource name'),
|
||||
'',
|
||||
false
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setFunctionName('setBitmapFontAndTextureAtlasResourceName');
|
||||
object
|
||||
.addAction(
|
||||
'SetBitmapFontAndTextureAtlasResourceName2',
|
||||
_('Bitmap files resources'),
|
||||
_('Change the Bitmap Font and/or the atlas image used by the object.'),
|
||||
_(
|
||||
'Set the bitmap font of _PARAM0_ to _PARAM1_ and the atlas to _PARAM2_'
|
||||
),
|
||||
'',
|
||||
'res/actions/font24.png',
|
||||
'res/actions/font.png'
|
||||
)
|
||||
.addParameter('object', _('Bitmap text'), 'BitmapTextObject', false)
|
||||
.addParameter(
|
||||
'bitmapFontResource',
|
||||
_('Bitmap font resource name'),
|
||||
'',
|
||||
false
|
||||
)
|
||||
.addParameter(
|
||||
'imageResource',
|
||||
_('Texture atlas resource name'),
|
||||
'',
|
||||
false
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setFunctionName('setBitmapFontAndTextureAtlasResourceName');
|
||||
|
||||
object
|
||||
.addExpressionAndCondition(
|
||||
@@ -451,10 +440,7 @@ module.exports = {
|
||||
* But it is recommended to create tests for the behaviors/objects properties you created
|
||||
* to avoid mistakes.
|
||||
*/
|
||||
runExtensionSanityTests: function (
|
||||
gd /*: libGDevelop */,
|
||||
extension /*: gdPlatformExtension*/
|
||||
) {
|
||||
runExtensionSanityTests: function (gd, extension) {
|
||||
return [];
|
||||
},
|
||||
/**
|
||||
@@ -462,9 +448,7 @@ module.exports = {
|
||||
*
|
||||
* ℹ️ Run `node import-GDJS-Runtime.js` (in newIDE/app/scripts) if you make any change.
|
||||
*/
|
||||
registerEditorConfigurations: function (
|
||||
objectsEditorService /*: ObjectsEditorService */
|
||||
) {
|
||||
registerEditorConfigurations: function (objectsEditorService) {
|
||||
objectsEditorService.registerEditorConfiguration(
|
||||
'BitmapText::BitmapTextObject',
|
||||
objectsEditorService.getDefaultObjectJsImplementationPropertiesEditor({
|
||||
@@ -477,9 +461,7 @@ module.exports = {
|
||||
*
|
||||
* ℹ️ Run `node import-GDJS-Runtime.js` (in newIDE/app/scripts) if you make any change.
|
||||
*/
|
||||
registerInstanceRenderers: function (
|
||||
objectsRenderingService /*: ObjectsRenderingService */
|
||||
) {
|
||||
registerInstanceRenderers: function (objectsRenderingService) {
|
||||
const RenderedInstance = objectsRenderingService.RenderedInstance;
|
||||
const PIXI = objectsRenderingService.PIXI;
|
||||
|
||||
@@ -649,156 +631,144 @@ module.exports = {
|
||||
};
|
||||
|
||||
/**
|
||||
* Renderer for instances of BitmapText inside the IDE.
|
||||
*
|
||||
* @extends RenderedBitmapTextInstance
|
||||
* @class RenderedBitmapTextInstance
|
||||
* @constructor
|
||||
* Return the path to the thumbnail of the specified object.
|
||||
* This is called to update the PIXI object on the scene editor
|
||||
*/
|
||||
function RenderedBitmapTextInstance(
|
||||
project,
|
||||
layout,
|
||||
instance,
|
||||
associatedObjectConfiguration,
|
||||
pixiContainer,
|
||||
pixiResourcesLoader
|
||||
) {
|
||||
RenderedInstance.call(
|
||||
this,
|
||||
class RenderedBitmapTextInstance extends RenderedInstance {
|
||||
static getThumbnail(project, resourcesLoader, objectConfiguration) {
|
||||
return 'JsPlatform/Extensions/bitmapfont24.png';
|
||||
}
|
||||
|
||||
constructor(
|
||||
project,
|
||||
layout,
|
||||
instance,
|
||||
associatedObjectConfiguration,
|
||||
pixiContainer,
|
||||
pixiResourcesLoader
|
||||
);
|
||||
|
||||
// We'll track changes of the font to trigger the loading of the new font.
|
||||
this._currentBitmapFontResourceName = '';
|
||||
this._currentTextureAtlasResourceName = '';
|
||||
|
||||
this._pixiObject = new PIXI.BitmapText('', {
|
||||
// Use a default font. The proper font will be loaded in `update` method.
|
||||
fontName: getDefaultBitmapFont().font,
|
||||
});
|
||||
|
||||
this._pixiObject.anchor.x = 0.5;
|
||||
this._pixiObject.anchor.y = 0.5;
|
||||
this._pixiContainer.addChild(this._pixiObject);
|
||||
this.update();
|
||||
}
|
||||
RenderedBitmapTextInstance.prototype = Object.create(
|
||||
RenderedInstance.prototype
|
||||
);
|
||||
|
||||
/**
|
||||
* Return the path to the thumbnail of the specified object.
|
||||
*/
|
||||
RenderedBitmapTextInstance.getThumbnail = function (
|
||||
project,
|
||||
resourcesLoader,
|
||||
objectConfiguration
|
||||
) {
|
||||
return 'JsPlatform/Extensions/bitmapfont24.png';
|
||||
};
|
||||
|
||||
// This is called to update the PIXI object on the scene editor
|
||||
RenderedBitmapTextInstance.prototype.update = function () {
|
||||
const properties = this._associatedObjectConfiguration.getProperties();
|
||||
|
||||
// Update the rendered text properties (note: Pixi is only
|
||||
// applying changes if there were changed).
|
||||
const rawText = properties.get('text').getValue();
|
||||
this._pixiObject.text = rawText;
|
||||
|
||||
const opacity = properties.get('opacity').getValue();
|
||||
this._pixiObject.alpha = opacity / 255;
|
||||
|
||||
const align = properties.get('align').getValue();
|
||||
this._pixiObject.align = align;
|
||||
|
||||
const color = properties.get('tint').getValue();
|
||||
this._pixiObject.tint =
|
||||
objectsRenderingService.rgbOrHexToHexNumber(color);
|
||||
|
||||
const scale = properties.get('scale').getValue() || 1;
|
||||
this._pixiObject.scale.set(scale);
|
||||
|
||||
// Track the changes in font to load the new requested font.
|
||||
const bitmapFontResourceName = properties
|
||||
.get('bitmapFontResourceName')
|
||||
.getValue();
|
||||
const textureAtlasResourceName = properties
|
||||
.get('textureAtlasResourceName')
|
||||
.getValue();
|
||||
|
||||
if (
|
||||
this._currentBitmapFontResourceName !== bitmapFontResourceName ||
|
||||
this._currentTextureAtlasResourceName !== textureAtlasResourceName
|
||||
) {
|
||||
// Release the old font (if it was installed).
|
||||
releaseBitmapFont(this._pixiObject.fontName);
|
||||
super(
|
||||
project,
|
||||
layout,
|
||||
instance,
|
||||
associatedObjectConfiguration,
|
||||
pixiContainer,
|
||||
pixiResourcesLoader
|
||||
);
|
||||
|
||||
// Temporarily go back to the default font, as the PIXI.BitmapText
|
||||
// object does not support being displayed with a font not installed at all.
|
||||
// It will be replaced as soon as the proper font is loaded.
|
||||
this._pixiObject.fontName = getDefaultBitmapFont().font;
|
||||
// We'll track changes of the font to trigger the loading of the new font.
|
||||
this._currentBitmapFontResourceName = '';
|
||||
this._currentTextureAtlasResourceName = '';
|
||||
|
||||
this._currentBitmapFontResourceName = bitmapFontResourceName;
|
||||
this._currentTextureAtlasResourceName = textureAtlasResourceName;
|
||||
obtainBitmapFont(
|
||||
this._pixiResourcesLoader,
|
||||
this._project,
|
||||
this._currentBitmapFontResourceName,
|
||||
this._currentTextureAtlasResourceName
|
||||
).then((bitmapFont) => {
|
||||
this._pixiObject.fontName = bitmapFont.font;
|
||||
this._pixiObject.fontSize = bitmapFont.size;
|
||||
this._pixiObject.dirty = true;
|
||||
this._pixiObject = new PIXI.BitmapText('', {
|
||||
// Use a default font. The proper font will be loaded in `update` method.
|
||||
fontName: getDefaultBitmapFont().font,
|
||||
});
|
||||
|
||||
this._pixiObject.anchor.x = 0.5;
|
||||
this._pixiObject.anchor.y = 0.5;
|
||||
this._pixiContainer.addChild(this._pixiObject);
|
||||
this.update();
|
||||
}
|
||||
|
||||
// Set up the wrapping width if enabled.
|
||||
const wordWrap = properties.get('wordWrap').getValue() === 'true';
|
||||
if (wordWrap && this._instance.hasCustomSize()) {
|
||||
this._pixiObject.maxWidth =
|
||||
this.getCustomWidth() / this._pixiObject.scale.x;
|
||||
this._pixiObject.dirty = true;
|
||||
} else {
|
||||
this._pixiObject.maxWidth = 0;
|
||||
this._pixiObject.dirty = true;
|
||||
update() {
|
||||
const properties = this._associatedObjectConfiguration.getProperties();
|
||||
|
||||
// Update the rendered text properties (note: Pixi is only
|
||||
// applying changes if there were changed).
|
||||
const rawText = properties.get('text').getValue();
|
||||
this._pixiObject.text = rawText;
|
||||
|
||||
const opacity = +properties.get('opacity').getValue();
|
||||
this._pixiObject.alpha = opacity / 255;
|
||||
|
||||
const align = properties.get('align').getValue();
|
||||
this._pixiObject.align = align;
|
||||
|
||||
const color = properties.get('tint').getValue();
|
||||
this._pixiObject.tint = objectsRenderingService.rgbOrHexToHexNumber(
|
||||
color
|
||||
);
|
||||
|
||||
const scale = +(properties.get('scale').getValue() || 1);
|
||||
this._pixiObject.scale.set(scale);
|
||||
|
||||
// Track the changes in font to load the new requested font.
|
||||
const bitmapFontResourceName = properties
|
||||
.get('bitmapFontResourceName')
|
||||
.getValue();
|
||||
const textureAtlasResourceName = properties
|
||||
.get('textureAtlasResourceName')
|
||||
.getValue();
|
||||
|
||||
if (
|
||||
this._currentBitmapFontResourceName !== bitmapFontResourceName ||
|
||||
this._currentTextureAtlasResourceName !== textureAtlasResourceName
|
||||
) {
|
||||
// Release the old font (if it was installed).
|
||||
releaseBitmapFont(this._pixiObject.fontName);
|
||||
|
||||
// Temporarily go back to the default font, as the PIXI.BitmapText
|
||||
// object does not support being displayed with a font not installed at all.
|
||||
// It will be replaced as soon as the proper font is loaded.
|
||||
this._pixiObject.fontName = getDefaultBitmapFont().font;
|
||||
|
||||
this._currentBitmapFontResourceName = bitmapFontResourceName;
|
||||
this._currentTextureAtlasResourceName = textureAtlasResourceName;
|
||||
obtainBitmapFont(
|
||||
this._pixiResourcesLoader,
|
||||
this._project,
|
||||
this._currentBitmapFontResourceName,
|
||||
this._currentTextureAtlasResourceName
|
||||
).then((bitmapFont) => {
|
||||
this._pixiObject.fontName = bitmapFont.font;
|
||||
this._pixiObject.fontSize = bitmapFont.size;
|
||||
this._pixiObject.dirty = true;
|
||||
});
|
||||
}
|
||||
|
||||
// Set up the wrapping width if enabled.
|
||||
const wordWrap = properties.get('wordWrap').getValue() === 'true';
|
||||
if (wordWrap && this._instance.hasCustomSize()) {
|
||||
this._pixiObject.maxWidth =
|
||||
this.getCustomWidth() / this._pixiObject.scale.x;
|
||||
this._pixiObject.dirty = true;
|
||||
} else {
|
||||
this._pixiObject.maxWidth = 0;
|
||||
this._pixiObject.dirty = true;
|
||||
}
|
||||
|
||||
this._pixiObject.position.x =
|
||||
this._instance.getX() + (this._pixiObject.textWidth * scale) / 2;
|
||||
this._pixiObject.position.y =
|
||||
this._instance.getY() + (this._pixiObject.textHeight * scale) / 2;
|
||||
this._pixiObject.rotation = RenderedInstance.toRad(
|
||||
this._instance.getAngle()
|
||||
);
|
||||
}
|
||||
|
||||
this._pixiObject.position.x =
|
||||
this._instance.getX() + (this._pixiObject.textWidth * scale) / 2;
|
||||
this._pixiObject.position.y =
|
||||
this._instance.getY() + (this._pixiObject.textHeight * scale) / 2;
|
||||
this._pixiObject.rotation = RenderedInstance.toRad(
|
||||
this._instance.getAngle()
|
||||
);
|
||||
};
|
||||
onRemovedFromScene() {
|
||||
RenderedInstance.prototype.onRemovedFromScene.call(this);
|
||||
|
||||
RenderedBitmapTextInstance.prototype.onRemovedFromScene = function () {
|
||||
RenderedInstance.prototype.onRemovedFromScene.call(this);
|
||||
const fontName = this._pixiObject.fontName;
|
||||
this._pixiObject.destroy();
|
||||
releaseBitmapFont(fontName);
|
||||
}
|
||||
|
||||
const fontName = this._pixiObject.fontName;
|
||||
this._pixiObject.destroy();
|
||||
releaseBitmapFont(fontName);
|
||||
};
|
||||
/**
|
||||
* Return the width of the instance, when it's not resized.
|
||||
*/
|
||||
getDefaultWidth() {
|
||||
return this._pixiObject.width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the width of the instance, when it's not resized.
|
||||
*/
|
||||
RenderedBitmapTextInstance.prototype.getDefaultWidth = function () {
|
||||
return this._pixiObject.width;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the height of the instance, when it's not resized.
|
||||
*/
|
||||
RenderedBitmapTextInstance.prototype.getDefaultHeight = function () {
|
||||
return this._pixiObject.height;
|
||||
};
|
||||
/**
|
||||
* Return the height of the instance, when it's not resized.
|
||||
*/
|
||||
getDefaultHeight() {
|
||||
return this._pixiObject.height;
|
||||
}
|
||||
}
|
||||
|
||||
objectsRenderingService.registerInstanceRenderer(
|
||||
'BitmapText::BitmapTextObject',
|
||||
|
@@ -1,4 +1,5 @@
|
||||
// @flow
|
||||
//@ts-check
|
||||
/// <reference path="../JsExtensionTypes.d.ts" />
|
||||
/**
|
||||
* This is a declaration of an extension for GDevelop 5.
|
||||
*
|
||||
@@ -12,18 +13,9 @@
|
||||
* More information on https://github.com/4ian/GDevelop/blob/master/newIDE/README-extensions.md
|
||||
*/
|
||||
|
||||
/*::
|
||||
// Import types to allow Flow to do static type checking on this file.
|
||||
// Extensions declaration are typed using Flow (like the editor), but the files
|
||||
// for the game engine are checked with TypeScript annotations.
|
||||
import { type ObjectsRenderingService, type ObjectsEditorService } from '../JsExtensionTypes.flow.js'
|
||||
*/
|
||||
|
||||
/** @type {ExtensionModule} */
|
||||
module.exports = {
|
||||
createExtension: function (
|
||||
_ /*: (string) => string */,
|
||||
gd /*: libGDevelop */
|
||||
) {
|
||||
createExtension: function (_, gd) {
|
||||
const extension = new gd.PlatformExtension();
|
||||
extension
|
||||
.setExtensionInformation(
|
||||
@@ -114,10 +106,7 @@ module.exports = {
|
||||
|
||||
return extension;
|
||||
},
|
||||
runExtensionSanityTests: function (
|
||||
gd /*: libGDevelop */,
|
||||
extension /*: gdPlatformExtension*/
|
||||
) {
|
||||
runExtensionSanityTests: function (gd, extension) {
|
||||
return [];
|
||||
},
|
||||
};
|
||||
|
@@ -1,4 +1,5 @@
|
||||
// @flow
|
||||
//@ts-check
|
||||
/// <reference path="../JsExtensionTypes.d.ts" />
|
||||
/**
|
||||
* This is a declaration of an extension for GDevelop 5.
|
||||
*
|
||||
@@ -12,450 +13,389 @@
|
||||
* More information on https://github.com/4ian/GDevelop/blob/master/newIDE/README-extensions.md
|
||||
*/
|
||||
|
||||
/*::
|
||||
// Import types to allow Flow to do static type checking on this file.
|
||||
// Extensions declaration are typed using Flow (like the editor), but the files
|
||||
// for the game engine are checked with TypeScript annotations.
|
||||
import { type ObjectsRenderingService, type ObjectsEditorService } from '../JsExtensionTypes.flow.js'
|
||||
*/
|
||||
|
||||
/** @type {ExtensionModule} */
|
||||
module.exports = {
|
||||
createExtension: function(_/*: (string) => string */, gd/*: libGDevelop */) {
|
||||
createExtension: function (_, gd) {
|
||||
const extension = new gd.PlatformExtension();
|
||||
extension.setExtensionInformation(
|
||||
"DeviceSensors",
|
||||
_("Device sensors"),
|
||||
_(
|
||||
"Allow the game to access the sensors of a mobile device."
|
||||
),
|
||||
"Matthias Meike",
|
||||
"Open source (MIT License)"
|
||||
).setExtensionHelpPath("/all-features/device-sensors")
|
||||
.setCategory('Input');
|
||||
extension.addInstructionOrExpressionGroupMetadata(_("Device sensors"))
|
||||
.setIcon("JsPlatform/Extensions/orientation_active32.png");
|
||||
extension
|
||||
.setExtensionInformation(
|
||||
'DeviceSensors',
|
||||
_('Device sensors'),
|
||||
_('Allow the game to access the sensors of a mobile device.'),
|
||||
'Matthias Meike',
|
||||
'Open source (MIT License)'
|
||||
)
|
||||
.setExtensionHelpPath('/all-features/device-sensors')
|
||||
.setCategory('Input');
|
||||
extension
|
||||
.addInstructionOrExpressionGroupMetadata(_('Device sensors'))
|
||||
.setIcon('JsPlatform/Extensions/orientation_active32.png');
|
||||
|
||||
extension
|
||||
.addCondition(
|
||||
"OrientationSensorActive",
|
||||
_("Sensor active"),
|
||||
'OrientationSensorActive',
|
||||
_('Sensor active'),
|
||||
_(
|
||||
"The condition is true if the device orientation sensor is currently active"
|
||||
'The condition is true if the device orientation sensor is currently active'
|
||||
),
|
||||
_("Orientation sensor is active"),
|
||||
_("Orientation"),
|
||||
"JsPlatform/Extensions/orientation_active32.png",
|
||||
"JsPlatform/Extensions/orientation_active32.png"
|
||||
_('Orientation sensor is active'),
|
||||
_('Orientation'),
|
||||
'JsPlatform/Extensions/orientation_active32.png',
|
||||
'JsPlatform/Extensions/orientation_active32.png'
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile(
|
||||
"Extensions/DeviceSensors/devicesensortools.js"
|
||||
)
|
||||
.setFunctionName("gdjs.deviceSensors.orientation.isActive");
|
||||
.setIncludeFile('Extensions/DeviceSensors/devicesensortools.js')
|
||||
.setFunctionName('gdjs.deviceSensors.orientation.isActive');
|
||||
|
||||
extension
|
||||
extension
|
||||
.addCondition(
|
||||
"OrientationAlpha",
|
||||
_("Compare the value of orientation alpha"),
|
||||
_(
|
||||
"Compare the value of orientation alpha. (Range: 0 to 360°)"
|
||||
),
|
||||
_("the orientation alpha"),
|
||||
_("Orientation"),
|
||||
"JsPlatform/Extensions/orientation_alpha32.png",
|
||||
"JsPlatform/Extensions/orientation_alpha32.png"
|
||||
'OrientationAlpha',
|
||||
_('Compare the value of orientation alpha'),
|
||||
_('Compare the value of orientation alpha. (Range: 0 to 360°)'),
|
||||
_('the orientation alpha'),
|
||||
_('Orientation'),
|
||||
'JsPlatform/Extensions/orientation_alpha32.png',
|
||||
'JsPlatform/Extensions/orientation_alpha32.png'
|
||||
)
|
||||
.addParameter("relationalOperator", _("Sign of the test"), "number")
|
||||
.addParameter("expression", _("Value"))
|
||||
.addParameter('relationalOperator', _('Sign of the test'), 'number')
|
||||
.addParameter('expression', _('Value'))
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile(
|
||||
"Extensions/DeviceSensors/devicesensortools.js"
|
||||
)
|
||||
.setFunctionName("gdjs.deviceSensors.orientation.getOrientationAlpha");
|
||||
.setIncludeFile('Extensions/DeviceSensors/devicesensortools.js')
|
||||
.setFunctionName('gdjs.deviceSensors.orientation.getOrientationAlpha');
|
||||
|
||||
extension
|
||||
extension
|
||||
.addCondition(
|
||||
"OrientationBeta",
|
||||
_("Compare the value of orientation beta"),
|
||||
_(
|
||||
"Compare the value of orientation beta. (Range: -180 to 180°)"
|
||||
),
|
||||
_("the orientation beta"),
|
||||
_("Orientation"),
|
||||
"JsPlatform/Extensions/orientation_beta32.png",
|
||||
"JsPlatform/Extensions/orientation_beta32.png"
|
||||
'OrientationBeta',
|
||||
_('Compare the value of orientation beta'),
|
||||
_('Compare the value of orientation beta. (Range: -180 to 180°)'),
|
||||
_('the orientation beta'),
|
||||
_('Orientation'),
|
||||
'JsPlatform/Extensions/orientation_beta32.png',
|
||||
'JsPlatform/Extensions/orientation_beta32.png'
|
||||
)
|
||||
.addParameter("relationalOperator", _("Sign of the test"), "number")
|
||||
.addParameter("expression", _("Value"))
|
||||
.addParameter('relationalOperator', _('Sign of the test'), 'number')
|
||||
.addParameter('expression', _('Value'))
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile(
|
||||
"Extensions/DeviceSensors/devicesensortools.js"
|
||||
)
|
||||
.setFunctionName("gdjs.deviceSensors.orientation.getOrientationBeta");
|
||||
.setIncludeFile('Extensions/DeviceSensors/devicesensortools.js')
|
||||
.setFunctionName('gdjs.deviceSensors.orientation.getOrientationBeta');
|
||||
|
||||
extension
|
||||
extension
|
||||
.addCondition(
|
||||
"OrientationGamma",
|
||||
_("Compare the value of orientation gamma"),
|
||||
_(
|
||||
"Compare the value of orientation gamma. (Range: -90 to 90°)"
|
||||
),
|
||||
_("the orientation gamma"),
|
||||
_("Orientation"),
|
||||
"JsPlatform/Extensions/orientation_gamma32.png",
|
||||
"JsPlatform/Extensions/orientation_gamma32.png"
|
||||
'OrientationGamma',
|
||||
_('Compare the value of orientation gamma'),
|
||||
_('Compare the value of orientation gamma. (Range: -90 to 90°)'),
|
||||
_('the orientation gamma'),
|
||||
_('Orientation'),
|
||||
'JsPlatform/Extensions/orientation_gamma32.png',
|
||||
'JsPlatform/Extensions/orientation_gamma32.png'
|
||||
)
|
||||
.addParameter("relationalOperator", _("Sign of the test"), "number")
|
||||
.addParameter("expression", _("Value"))
|
||||
.addParameter('relationalOperator', _('Sign of the test'), 'number')
|
||||
.addParameter('expression', _('Value'))
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile(
|
||||
"Extensions/DeviceSensors/devicesensortools.js"
|
||||
)
|
||||
.setFunctionName("gdjs.deviceSensors.orientation.getOrientationGamma");
|
||||
.setIncludeFile('Extensions/DeviceSensors/devicesensortools.js')
|
||||
.setFunctionName('gdjs.deviceSensors.orientation.getOrientationGamma');
|
||||
|
||||
extension
|
||||
.addAction(
|
||||
"ActivateOrientationListener",
|
||||
_("Activate orientation sensor"),
|
||||
_("Activate the orientation sensor. (remember to turn it off again)"),
|
||||
_("Activate the orientation sensor."),
|
||||
_("Orientation"),
|
||||
"JsPlatform/Extensions/orientation_active32.png",
|
||||
"JsPlatform/Extensions/orientation_active32.png"
|
||||
'ActivateOrientationListener',
|
||||
_('Activate orientation sensor'),
|
||||
_('Activate the orientation sensor. (remember to turn it off again)'),
|
||||
_('Activate the orientation sensor.'),
|
||||
_('Orientation'),
|
||||
'JsPlatform/Extensions/orientation_active32.png',
|
||||
'JsPlatform/Extensions/orientation_active32.png'
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile(
|
||||
"Extensions/DeviceSensors/devicesensortools.js"
|
||||
)
|
||||
.setFunctionName("gdjs.deviceSensors.orientation.activateOrientationSensor");
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile('Extensions/DeviceSensors/devicesensortools.js')
|
||||
.setFunctionName(
|
||||
'gdjs.deviceSensors.orientation.activateOrientationSensor'
|
||||
);
|
||||
|
||||
extension
|
||||
.addAction(
|
||||
"DeactivateOrientationListener",
|
||||
_("Deactivate orientation sensor"),
|
||||
_("Deactivate the orientation sensor."),
|
||||
_("Deactivate the orientation sensor."),
|
||||
_("Orientation"),
|
||||
"JsPlatform/Extensions/orientation_inactive32.png",
|
||||
"JsPlatform/Extensions/orientation_inactive32.png"
|
||||
'DeactivateOrientationListener',
|
||||
_('Deactivate orientation sensor'),
|
||||
_('Deactivate the orientation sensor.'),
|
||||
_('Deactivate the orientation sensor.'),
|
||||
_('Orientation'),
|
||||
'JsPlatform/Extensions/orientation_inactive32.png',
|
||||
'JsPlatform/Extensions/orientation_inactive32.png'
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile(
|
||||
"Extensions/DeviceSensors/devicesensortools.js"
|
||||
)
|
||||
.setFunctionName("gdjs.deviceSensors.orientation.deactivateOrientationSensor");
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile('Extensions/DeviceSensors/devicesensortools.js')
|
||||
.setFunctionName(
|
||||
'gdjs.deviceSensors.orientation.deactivateOrientationSensor'
|
||||
);
|
||||
|
||||
extension
|
||||
.addExpression(
|
||||
"OrientationAbsolute",
|
||||
_("Is Absolute"),
|
||||
_("Get if the devices orientation is absolute and not relative"),
|
||||
_("Orientation"),
|
||||
"JsPlatform/Extensions/orientation_absolute16.png"
|
||||
'OrientationAbsolute',
|
||||
_('Is Absolute'),
|
||||
_('Get if the devices orientation is absolute and not relative'),
|
||||
_('Orientation'),
|
||||
'JsPlatform/Extensions/orientation_absolute16.png'
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile(
|
||||
"Extensions/DeviceSensors/devicesensortools.js"
|
||||
)
|
||||
.setFunctionName("gdjs.deviceSensors.orientation.getOrientationAbsolute");
|
||||
.setIncludeFile('Extensions/DeviceSensors/devicesensortools.js')
|
||||
.setFunctionName('gdjs.deviceSensors.orientation.getOrientationAbsolute');
|
||||
|
||||
extension
|
||||
.addExpression(
|
||||
"OrientationAlpha",
|
||||
_("Alpha value"),
|
||||
_("Get the devices orientation Alpha (compass)"),
|
||||
_("Orientation"),
|
||||
"JsPlatform/Extensions/orientation_alpha16.png"
|
||||
'OrientationAlpha',
|
||||
_('Alpha value'),
|
||||
_('Get the devices orientation Alpha (compass)'),
|
||||
_('Orientation'),
|
||||
'JsPlatform/Extensions/orientation_alpha16.png'
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile(
|
||||
"Extensions/DeviceSensors/devicesensortools.js"
|
||||
)
|
||||
.setFunctionName("gdjs.deviceSensors.orientation.getOrientationAlpha");
|
||||
.setIncludeFile('Extensions/DeviceSensors/devicesensortools.js')
|
||||
.setFunctionName('gdjs.deviceSensors.orientation.getOrientationAlpha');
|
||||
|
||||
extension
|
||||
.addExpression(
|
||||
"OrientationBeta",
|
||||
_("Beta value"),
|
||||
_("Get the devices orientation Beta"),
|
||||
_("Orientation"),
|
||||
"JsPlatform/Extensions/orientation_beta16.png"
|
||||
'OrientationBeta',
|
||||
_('Beta value'),
|
||||
_('Get the devices orientation Beta'),
|
||||
_('Orientation'),
|
||||
'JsPlatform/Extensions/orientation_beta16.png'
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile(
|
||||
"Extensions/DeviceSensors/devicesensortools.js"
|
||||
)
|
||||
.setFunctionName("gdjs.deviceSensors.orientation.getOrientationBeta");
|
||||
.setIncludeFile('Extensions/DeviceSensors/devicesensortools.js')
|
||||
.setFunctionName('gdjs.deviceSensors.orientation.getOrientationBeta');
|
||||
|
||||
extension
|
||||
.addExpression(
|
||||
"OrientationGamma",
|
||||
_("Gamma value"),
|
||||
_("Get the devices orientation Gamma value"),
|
||||
_("Orientation"),
|
||||
"JsPlatform/Extensions/orientation_gamma16.png"
|
||||
'OrientationGamma',
|
||||
_('Gamma value'),
|
||||
_('Get the devices orientation Gamma value'),
|
||||
_('Orientation'),
|
||||
'JsPlatform/Extensions/orientation_gamma16.png'
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile(
|
||||
"Extensions/DeviceSensors/devicesensortools.js"
|
||||
)
|
||||
.setFunctionName("gdjs.deviceSensors.orientation.getOrientationGamma");
|
||||
.setIncludeFile('Extensions/DeviceSensors/devicesensortools.js')
|
||||
.setFunctionName('gdjs.deviceSensors.orientation.getOrientationGamma');
|
||||
|
||||
extension
|
||||
extension
|
||||
.addCondition(
|
||||
"MotionSensorActive",
|
||||
_("Sensor active"),
|
||||
'MotionSensorActive',
|
||||
_('Sensor active'),
|
||||
_(
|
||||
"The condition is true if the device motion sensor is currently active"
|
||||
'The condition is true if the device motion sensor is currently active'
|
||||
),
|
||||
_("Motion sensor is active"),
|
||||
_("Motion"),
|
||||
"JsPlatform/Extensions/motion_active32.png",
|
||||
"JsPlatform/Extensions/motion_active32.png"
|
||||
_('Motion sensor is active'),
|
||||
_('Motion'),
|
||||
'JsPlatform/Extensions/motion_active32.png',
|
||||
'JsPlatform/Extensions/motion_active32.png'
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile(
|
||||
"Extensions/DeviceSensors/devicesensortools.js"
|
||||
)
|
||||
.setFunctionName("gdjs.deviceSensors.motion.isActive");
|
||||
.setIncludeFile('Extensions/DeviceSensors/devicesensortools.js')
|
||||
.setFunctionName('gdjs.deviceSensors.motion.isActive');
|
||||
|
||||
extension
|
||||
extension
|
||||
.addCondition(
|
||||
"RotationAlpha",
|
||||
_("Compare the value of rotation alpha"),
|
||||
'RotationAlpha',
|
||||
_('Compare the value of rotation alpha'),
|
||||
_(
|
||||
"Compare the value of rotation alpha. (Note: few devices support this sensor)"
|
||||
'Compare the value of rotation alpha. (Note: few devices support this sensor)'
|
||||
),
|
||||
_("the rotation alpha"),
|
||||
_("Motion"),
|
||||
"JsPlatform/Extensions/motion_rotation_alpha32.png",
|
||||
"JsPlatform/Extensions/motion_rotation_alpha32.png"
|
||||
_('the rotation alpha'),
|
||||
_('Motion'),
|
||||
'JsPlatform/Extensions/motion_rotation_alpha32.png',
|
||||
'JsPlatform/Extensions/motion_rotation_alpha32.png'
|
||||
)
|
||||
.addParameter("relationalOperator", _("Sign of the test"), "number")
|
||||
.addParameter("expression", _("Value (m/s²)"))
|
||||
.addParameter('relationalOperator', _('Sign of the test'), 'number')
|
||||
.addParameter('expression', _('Value (m/s²)'))
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile(
|
||||
"Extensions/DeviceSensors/devicesensortools.js"
|
||||
)
|
||||
.setFunctionName("gdjs.deviceSensors.motion.getRotationAlpha");
|
||||
.setIncludeFile('Extensions/DeviceSensors/devicesensortools.js')
|
||||
.setFunctionName('gdjs.deviceSensors.motion.getRotationAlpha');
|
||||
|
||||
extension
|
||||
extension
|
||||
.addCondition(
|
||||
"RotationBeta",
|
||||
_("Compare the value of rotation beta"),
|
||||
'RotationBeta',
|
||||
_('Compare the value of rotation beta'),
|
||||
_(
|
||||
"Compare the value of rotation beta. (Note: few devices support this sensor)"
|
||||
'Compare the value of rotation beta. (Note: few devices support this sensor)'
|
||||
),
|
||||
_("the rotation beta"),
|
||||
_("Motion"),
|
||||
"JsPlatform/Extensions/motion_rotation_beta32.png",
|
||||
"JsPlatform/Extensions/motion_rotation_beta32.png"
|
||||
_('the rotation beta'),
|
||||
_('Motion'),
|
||||
'JsPlatform/Extensions/motion_rotation_beta32.png',
|
||||
'JsPlatform/Extensions/motion_rotation_beta32.png'
|
||||
)
|
||||
.addParameter("relationalOperator", _("Sign of the test"), "number")
|
||||
.addParameter("expression", _("Value (m/s²)"))
|
||||
.addParameter('relationalOperator', _('Sign of the test'), 'number')
|
||||
.addParameter('expression', _('Value (m/s²)'))
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile(
|
||||
"Extensions/DeviceSensors/devicesensortools.js"
|
||||
)
|
||||
.setFunctionName("gdjs.deviceSensors.motion.getRotationBeta");
|
||||
.setIncludeFile('Extensions/DeviceSensors/devicesensortools.js')
|
||||
.setFunctionName('gdjs.deviceSensors.motion.getRotationBeta');
|
||||
|
||||
extension
|
||||
extension
|
||||
.addCondition(
|
||||
"RotationGamma",
|
||||
_("Compare the value of rotation gamma"),
|
||||
'RotationGamma',
|
||||
_('Compare the value of rotation gamma'),
|
||||
_(
|
||||
"Compare the value of rotation gamma. (Note: few devices support this sensor)"
|
||||
'Compare the value of rotation gamma. (Note: few devices support this sensor)'
|
||||
),
|
||||
_("the rotation gamma"),
|
||||
_("Motion"),
|
||||
"JsPlatform/Extensions/motion_rotation_gamma32.png",
|
||||
"JsPlatform/Extensions/motion_rotation_gamma32.png"
|
||||
_('the rotation gamma'),
|
||||
_('Motion'),
|
||||
'JsPlatform/Extensions/motion_rotation_gamma32.png',
|
||||
'JsPlatform/Extensions/motion_rotation_gamma32.png'
|
||||
)
|
||||
.addParameter("relationalOperator", _("Sign of the test"), "number")
|
||||
.addParameter("expression", _("Value (m/s²)"))
|
||||
.addParameter('relationalOperator', _('Sign of the test'), 'number')
|
||||
.addParameter('expression', _('Value (m/s²)'))
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile(
|
||||
"Extensions/DeviceSensors/devicesensortools.js"
|
||||
)
|
||||
.setFunctionName("gdjs.deviceSensors.motion.getRotationGamma");
|
||||
.setIncludeFile('Extensions/DeviceSensors/devicesensortools.js')
|
||||
.setFunctionName('gdjs.deviceSensors.motion.getRotationGamma');
|
||||
|
||||
extension
|
||||
extension
|
||||
.addCondition(
|
||||
"AccelerationX",
|
||||
_("Compare the value of acceleration on X-axis"),
|
||||
_(
|
||||
"Compare the value of acceleration on the X-axis (m/s²)."
|
||||
),
|
||||
_("the acceleration X"),
|
||||
_("Motion"),
|
||||
"JsPlatform/Extensions/motion_acceleration_x32.png",
|
||||
"JsPlatform/Extensions/motion_acceleration_x32.png"
|
||||
'AccelerationX',
|
||||
_('Compare the value of acceleration on X-axis'),
|
||||
_('Compare the value of acceleration on the X-axis (m/s²).'),
|
||||
_('the acceleration X'),
|
||||
_('Motion'),
|
||||
'JsPlatform/Extensions/motion_acceleration_x32.png',
|
||||
'JsPlatform/Extensions/motion_acceleration_x32.png'
|
||||
)
|
||||
.addParameter("relationalOperator", _("Sign of the test"), "number")
|
||||
.addParameter("expression", _("Value (m/s²)"))
|
||||
.addParameter('relationalOperator', _('Sign of the test'), 'number')
|
||||
.addParameter('expression', _('Value (m/s²)'))
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile(
|
||||
"Extensions/DeviceSensors/devicesensortools.js"
|
||||
)
|
||||
.setFunctionName("gdjs.deviceSensors.motion.getAccelerationX");
|
||||
.setIncludeFile('Extensions/DeviceSensors/devicesensortools.js')
|
||||
.setFunctionName('gdjs.deviceSensors.motion.getAccelerationX');
|
||||
|
||||
extension
|
||||
extension
|
||||
.addCondition(
|
||||
"AccelerationY",
|
||||
_("Compare the value of acceleration on Y-axis"),
|
||||
_(
|
||||
"Compare the value of acceleration on the Y-axis (m/s²)."
|
||||
),
|
||||
_("the acceleration Y"),
|
||||
_("Motion"),
|
||||
"JsPlatform/Extensions/motion_acceleration_y32.png",
|
||||
"JsPlatform/Extensions/motion_acceleration_y32.png"
|
||||
'AccelerationY',
|
||||
_('Compare the value of acceleration on Y-axis'),
|
||||
_('Compare the value of acceleration on the Y-axis (m/s²).'),
|
||||
_('the acceleration Y'),
|
||||
_('Motion'),
|
||||
'JsPlatform/Extensions/motion_acceleration_y32.png',
|
||||
'JsPlatform/Extensions/motion_acceleration_y32.png'
|
||||
)
|
||||
.addParameter("relationalOperator", _("Sign of the test"), "number")
|
||||
.addParameter("expression", _("Value (m/s²)"))
|
||||
.addParameter('relationalOperator', _('Sign of the test'), 'number')
|
||||
.addParameter('expression', _('Value (m/s²)'))
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile(
|
||||
"Extensions/DeviceSensors/devicesensortools.js"
|
||||
)
|
||||
.setFunctionName("gdjs.deviceSensors.motion.getAccelerationY");
|
||||
.setIncludeFile('Extensions/DeviceSensors/devicesensortools.js')
|
||||
.setFunctionName('gdjs.deviceSensors.motion.getAccelerationY');
|
||||
|
||||
extension
|
||||
extension
|
||||
.addCondition(
|
||||
"AccelerationZ",
|
||||
_("Compare the value of acceleration on Z-axis"),
|
||||
_(
|
||||
"Compare the value of acceleration on the Z-axis (m/s²)."
|
||||
),
|
||||
_("the acceleration Z"),
|
||||
_("Motion"),
|
||||
"JsPlatform/Extensions/motion_acceleration_z32.png",
|
||||
"JsPlatform/Extensions/motion_acceleration_z32.png"
|
||||
'AccelerationZ',
|
||||
_('Compare the value of acceleration on Z-axis'),
|
||||
_('Compare the value of acceleration on the Z-axis (m/s²).'),
|
||||
_('the acceleration Z'),
|
||||
_('Motion'),
|
||||
'JsPlatform/Extensions/motion_acceleration_z32.png',
|
||||
'JsPlatform/Extensions/motion_acceleration_z32.png'
|
||||
)
|
||||
.addParameter("relationalOperator", _("Sign of the test"), "number")
|
||||
.addParameter("expression", _("Value (m/s²)"))
|
||||
.addParameter('relationalOperator', _('Sign of the test'), 'number')
|
||||
.addParameter('expression', _('Value (m/s²)'))
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile(
|
||||
"Extensions/DeviceSensors/devicesensortools.js"
|
||||
)
|
||||
.setFunctionName("gdjs.deviceSensors.motion.getAccelerationZ");
|
||||
.setIncludeFile('Extensions/DeviceSensors/devicesensortools.js')
|
||||
.setFunctionName('gdjs.deviceSensors.motion.getAccelerationZ');
|
||||
|
||||
extension
|
||||
.addAction(
|
||||
"ActivateMotionListener",
|
||||
_("Activate motion sensor"),
|
||||
_("Activate the motion sensor. (remember to turn it off again)"),
|
||||
_("Activate the motion sensor."),
|
||||
_("Motion"),
|
||||
"JsPlatform/Extensions/motion_active32.png",
|
||||
"JsPlatform/Extensions/motion_active32.png"
|
||||
'ActivateMotionListener',
|
||||
_('Activate motion sensor'),
|
||||
_('Activate the motion sensor. (remember to turn it off again)'),
|
||||
_('Activate the motion sensor.'),
|
||||
_('Motion'),
|
||||
'JsPlatform/Extensions/motion_active32.png',
|
||||
'JsPlatform/Extensions/motion_active32.png'
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile(
|
||||
"Extensions/DeviceSensors/devicesensortools.js"
|
||||
)
|
||||
.setFunctionName("gdjs.deviceSensors.motion.activateMotionSensor");
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile('Extensions/DeviceSensors/devicesensortools.js')
|
||||
.setFunctionName('gdjs.deviceSensors.motion.activateMotionSensor');
|
||||
|
||||
extension
|
||||
.addAction(
|
||||
"DeactivateMotionListener",
|
||||
_("Deactivate motion sensor"),
|
||||
_("Deactivate the motion sensor."),
|
||||
_("Deactivate the motion sensor."),
|
||||
_("Motion"),
|
||||
"JsPlatform/Extensions/motion_inactive32.png",
|
||||
"JsPlatform/Extensions/motion_inactive32.png"
|
||||
'DeactivateMotionListener',
|
||||
_('Deactivate motion sensor'),
|
||||
_('Deactivate the motion sensor.'),
|
||||
_('Deactivate the motion sensor.'),
|
||||
_('Motion'),
|
||||
'JsPlatform/Extensions/motion_inactive32.png',
|
||||
'JsPlatform/Extensions/motion_inactive32.png'
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile(
|
||||
"Extensions/DeviceSensors/devicesensortools.js"
|
||||
)
|
||||
.setFunctionName("gdjs.deviceSensors.motion.deactivateMotionSensor");
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile('Extensions/DeviceSensors/devicesensortools.js')
|
||||
.setFunctionName('gdjs.deviceSensors.motion.deactivateMotionSensor');
|
||||
|
||||
extension
|
||||
.addExpression(
|
||||
"RotationAlpha",
|
||||
_("Alpha value"),
|
||||
_("Get the devices rotation Alpha"),
|
||||
_("Motion"),
|
||||
"JsPlatform/Extensions/motion_rotation_alpha16.png"
|
||||
'RotationAlpha',
|
||||
_('Alpha value'),
|
||||
_('Get the devices rotation Alpha'),
|
||||
_('Motion'),
|
||||
'JsPlatform/Extensions/motion_rotation_alpha16.png'
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile(
|
||||
"Extensions/DeviceSensors/devicesensortools.js"
|
||||
)
|
||||
.setFunctionName("gdjs.deviceSensors.motion.getRotationAlpha");
|
||||
.setIncludeFile('Extensions/DeviceSensors/devicesensortools.js')
|
||||
.setFunctionName('gdjs.deviceSensors.motion.getRotationAlpha');
|
||||
|
||||
extension
|
||||
.addExpression(
|
||||
"RotationBeta",
|
||||
_("Beta value"),
|
||||
_("Get the devices rotation Beta"),
|
||||
_("Motion"),
|
||||
"JsPlatform/Extensions/motion_rotation_beta16.png"
|
||||
'RotationBeta',
|
||||
_('Beta value'),
|
||||
_('Get the devices rotation Beta'),
|
||||
_('Motion'),
|
||||
'JsPlatform/Extensions/motion_rotation_beta16.png'
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile(
|
||||
"Extensions/DeviceSensors/devicesensortools.js"
|
||||
)
|
||||
.setFunctionName("gdjs.deviceSensors.motion.getRotationBeta");
|
||||
.setIncludeFile('Extensions/DeviceSensors/devicesensortools.js')
|
||||
.setFunctionName('gdjs.deviceSensors.motion.getRotationBeta');
|
||||
|
||||
extension
|
||||
.addExpression(
|
||||
"RotationGamma",
|
||||
_("Gamma value"),
|
||||
_("Get the devices rotation Gamma"),
|
||||
_("Motion"),
|
||||
"JsPlatform/Extensions/motion_rotation_gamma16.png"
|
||||
'RotationGamma',
|
||||
_('Gamma value'),
|
||||
_('Get the devices rotation Gamma'),
|
||||
_('Motion'),
|
||||
'JsPlatform/Extensions/motion_rotation_gamma16.png'
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile(
|
||||
"Extensions/DeviceSensors/devicesensortools.js"
|
||||
)
|
||||
.setFunctionName("gdjs.deviceSensors.motion.getRotationGamma");
|
||||
.setIncludeFile('Extensions/DeviceSensors/devicesensortools.js')
|
||||
.setFunctionName('gdjs.deviceSensors.motion.getRotationGamma');
|
||||
|
||||
extension
|
||||
extension
|
||||
.addExpression(
|
||||
"AccelerationX",
|
||||
_("Acceleration X value"),
|
||||
_("Get the devices acceleration on the X-axis (m/s²)"),
|
||||
_("Motion"),
|
||||
"JsPlatform/Extensions/motion_acceleration_x16.png"
|
||||
'AccelerationX',
|
||||
_('Acceleration X value'),
|
||||
_('Get the devices acceleration on the X-axis (m/s²)'),
|
||||
_('Motion'),
|
||||
'JsPlatform/Extensions/motion_acceleration_x16.png'
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile(
|
||||
"Extensions/DeviceSensors/devicesensortools.js"
|
||||
)
|
||||
.setFunctionName("gdjs.deviceSensors.motion.getAccelerationX");
|
||||
.setIncludeFile('Extensions/DeviceSensors/devicesensortools.js')
|
||||
.setFunctionName('gdjs.deviceSensors.motion.getAccelerationX');
|
||||
|
||||
extension
|
||||
extension
|
||||
.addExpression(
|
||||
"AccelerationY",
|
||||
_("Acceleration Y value"),
|
||||
_("Get the devices acceleration on the Y-axis (m/s²)"),
|
||||
_("Motion"),
|
||||
"JsPlatform/Extensions/motion_acceleration_y16.png"
|
||||
'AccelerationY',
|
||||
_('Acceleration Y value'),
|
||||
_('Get the devices acceleration on the Y-axis (m/s²)'),
|
||||
_('Motion'),
|
||||
'JsPlatform/Extensions/motion_acceleration_y16.png'
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile(
|
||||
"Extensions/DeviceSensors/devicesensortools.js"
|
||||
)
|
||||
.setFunctionName("gdjs.deviceSensors.motion.getAccelerationY");
|
||||
.setIncludeFile('Extensions/DeviceSensors/devicesensortools.js')
|
||||
.setFunctionName('gdjs.deviceSensors.motion.getAccelerationY');
|
||||
|
||||
extension
|
||||
extension
|
||||
.addExpression(
|
||||
"AccelerationZ",
|
||||
_("Acceleration Z value"),
|
||||
_("Get the devices acceleration on the Z-axis (m/s²)"),
|
||||
_("Motion"),
|
||||
"JsPlatform/Extensions/motion_acceleration_z16.png"
|
||||
'AccelerationZ',
|
||||
_('Acceleration Z value'),
|
||||
_('Get the devices acceleration on the Z-axis (m/s²)'),
|
||||
_('Motion'),
|
||||
'JsPlatform/Extensions/motion_acceleration_z16.png'
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile(
|
||||
"Extensions/DeviceSensors/devicesensortools.js"
|
||||
)
|
||||
.setFunctionName("gdjs.deviceSensors.motion.getAccelerationZ");
|
||||
.setIncludeFile('Extensions/DeviceSensors/devicesensortools.js')
|
||||
.setFunctionName('gdjs.deviceSensors.motion.getAccelerationZ');
|
||||
|
||||
return extension;
|
||||
},
|
||||
runExtensionSanityTests: function(gd /*: libGDevelop */, extension /*: gdPlatformExtension*/) { return []; },
|
||||
runExtensionSanityTests: function (gd, extension) {
|
||||
return [];
|
||||
},
|
||||
};
|
||||
|
@@ -1,4 +1,5 @@
|
||||
// @flow
|
||||
//@ts-check
|
||||
/// <reference path="../JsExtensionTypes.d.ts" />
|
||||
/**
|
||||
* This is a declaration of an extension for GDevelop 5.
|
||||
*
|
||||
@@ -12,18 +13,9 @@
|
||||
* More information on https://github.com/4ian/GDevelop/blob/master/newIDE/README-extensions.md
|
||||
*/
|
||||
|
||||
/*::
|
||||
// Import types to allow Flow to do static type checking on this file.
|
||||
// Extensions declaration are typed using Flow (like the editor), but the files
|
||||
// for the game engine are checked with TypeScript annotations.
|
||||
import { type ObjectsRenderingService, type ObjectsEditorService } from '../JsExtensionTypes.flow.js'
|
||||
*/
|
||||
|
||||
/** @type {ExtensionModule} */
|
||||
module.exports = {
|
||||
createExtension: function (
|
||||
_ /*: (string) => string */,
|
||||
gd /*: libGDevelop */
|
||||
) {
|
||||
createExtension: function (_, gd) {
|
||||
const extension = new gd.PlatformExtension();
|
||||
extension
|
||||
.setExtensionInformation(
|
||||
@@ -36,8 +28,9 @@ module.exports = {
|
||||
)
|
||||
.setExtensionHelpPath('/all-features/device-vibration')
|
||||
.setCategory('User interface');
|
||||
extension.addInstructionOrExpressionGroupMetadata(_("Device vibration"))
|
||||
.setIcon("JsPlatform/Extensions/vibration_start32.png");
|
||||
extension
|
||||
.addInstructionOrExpressionGroupMetadata(_('Device vibration'))
|
||||
.setIcon('JsPlatform/Extensions/vibration_start32.png');
|
||||
|
||||
extension
|
||||
.addDependency()
|
||||
@@ -99,10 +92,7 @@ module.exports = {
|
||||
|
||||
return extension;
|
||||
},
|
||||
runExtensionSanityTests: function (
|
||||
gd /*: libGDevelop */,
|
||||
extension /*: gdPlatformExtension*/
|
||||
) {
|
||||
runExtensionSanityTests: function (gd, extension) {
|
||||
return [];
|
||||
},
|
||||
};
|
||||
|
@@ -1,4 +1,5 @@
|
||||
// @flow
|
||||
//@ts-check
|
||||
/// <reference path="../JsExtensionTypes.d.ts" />
|
||||
/**
|
||||
* This is a declaration of an extension for GDevelop 5.
|
||||
*
|
||||
@@ -12,18 +13,9 @@
|
||||
* More information on https://github.com/4ian/GDevelop/blob/master/newIDE/README-extensions.md
|
||||
*/
|
||||
|
||||
/*::
|
||||
// Import types to allow Flow to do static type checking on this file.
|
||||
// Extensions declaration are typed using Flow (like the editor), but the files
|
||||
// for the game engine are checked with TypeScript annotations.
|
||||
import { type ObjectsRenderingService, type ObjectsEditorService } from '../JsExtensionTypes.flow.js'
|
||||
*/
|
||||
|
||||
/** @type {ExtensionModule} */
|
||||
module.exports = {
|
||||
createExtension: function (
|
||||
_ /*: (string) => string */,
|
||||
gd /*: libGDevelop */
|
||||
) {
|
||||
createExtension: function (_, gd) {
|
||||
const extension = new gd.PlatformExtension();
|
||||
extension
|
||||
.setExtensionInformation(
|
||||
@@ -721,10 +713,7 @@ module.exports = {
|
||||
|
||||
return extension;
|
||||
},
|
||||
runExtensionSanityTests: function (
|
||||
gd /*: libGDevelop */,
|
||||
extension /*: gdPlatformExtension*/
|
||||
) {
|
||||
runExtensionSanityTests: function (gd, extension) {
|
||||
return [];
|
||||
},
|
||||
};
|
||||
|
@@ -1,4 +1,5 @@
|
||||
// @flow
|
||||
//@ts-check
|
||||
/// <reference path="../JsExtensionTypes.d.ts" />
|
||||
/**
|
||||
* This is a declaration of an extension for GDevelop 5.
|
||||
*
|
||||
@@ -12,28 +13,20 @@
|
||||
* More information on https://github.com/4ian/GDevelop/blob/master/newIDE/README-extensions.md
|
||||
*/
|
||||
|
||||
/*::
|
||||
// Import types to allow Flow to do static type checking on this file.
|
||||
// Extensions declaration are typed using Flow (like the editor), but the files
|
||||
// for the game engine are checked with TypeScript annotations.
|
||||
import { type ObjectsRenderingService, type ObjectsEditorService } from '../JsExtensionTypes.flow.js'
|
||||
*/
|
||||
|
||||
/** @type {ExtensionModule} */
|
||||
module.exports = {
|
||||
createExtension: function (
|
||||
_ /*: (string) => string */,
|
||||
gd /*: libGDevelop */
|
||||
) {
|
||||
createExtension: function (_, gd) {
|
||||
const extension = new gd.PlatformExtension();
|
||||
extension.setExtensionInformation(
|
||||
'Effects',
|
||||
'Effects',
|
||||
'Lots of different effects to be used in your game.',
|
||||
'Various contributors from PixiJS, PixiJS filters and GDevelop',
|
||||
'MIT'
|
||||
)
|
||||
.setCategory('Visual effect')
|
||||
.setExtensionHelpPath('/interface/scene-editor/layer-effects');
|
||||
extension
|
||||
.setExtensionInformation(
|
||||
'Effects',
|
||||
'Effects',
|
||||
'Lots of different effects to be used in your game.',
|
||||
'Various contributors from PixiJS, PixiJS filters and GDevelop',
|
||||
'MIT'
|
||||
)
|
||||
.setCategory('Visual effect')
|
||||
.setExtensionHelpPath('/interface/scene-editor/layer-effects');
|
||||
|
||||
// ℹ️ You can declare an effect here. Please order the effects by alphabetical order.
|
||||
// This file is for common effects that are well-known/"battle-tested". If you have an
|
||||
@@ -230,7 +223,11 @@ module.exports = {
|
||||
const blurEffect = extension
|
||||
.addEffect('Blur')
|
||||
.setFullName(_('Blur (Gaussian, slow - prefer to use Kawase blur)'))
|
||||
.setDescription(_('Blur the rendered image. This is slow, so prefer to use Kawase blur in most cases.'))
|
||||
.setDescription(
|
||||
_(
|
||||
'Blur the rendered image. This is slow, so prefer to use Kawase blur in most cases.'
|
||||
)
|
||||
)
|
||||
.markAsOnlyWorkingFor2D()
|
||||
.addIncludeFile('Extensions/Effects/blur-pixi-filter.js');
|
||||
const blurProperties = blurEffect.getProperties();
|
||||
@@ -728,13 +725,11 @@ module.exports = {
|
||||
const hslAdjustmentEffect = extension
|
||||
.addEffect('HslAdjustment')
|
||||
.setFullName(_('HSL Adjustment'))
|
||||
.setDescription(
|
||||
_(
|
||||
'Adjust hue, saturation and lightness.'
|
||||
)
|
||||
)
|
||||
.setDescription(_('Adjust hue, saturation and lightness.'))
|
||||
.markAsOnlyWorkingFor2D()
|
||||
.addIncludeFile('Extensions/Effects/pixi-filters/filter-hsl-adjustment.js')
|
||||
.addIncludeFile(
|
||||
'Extensions/Effects/pixi-filters/filter-hsl-adjustment.js'
|
||||
)
|
||||
.addIncludeFile('Extensions/Effects/hsl-adjustment-pixi-filter.js');
|
||||
const hslAdjustmentProperties = hslAdjustmentEffect.getProperties();
|
||||
hslAdjustmentProperties
|
||||
@@ -767,7 +762,9 @@ module.exports = {
|
||||
.addEffect('KawaseBlur')
|
||||
.setFullName(_('Blur (Kawase, fast)'))
|
||||
.setDescription(
|
||||
_('Blur the rendered image, with much better performance than Gaussian blur.')
|
||||
_(
|
||||
'Blur the rendered image, with much better performance than Gaussian blur.'
|
||||
)
|
||||
)
|
||||
.markAsOnlyWorkingFor2D()
|
||||
.addIncludeFile('Extensions/Effects/pixi-filters/filter-kawase-blur.js')
|
||||
@@ -816,9 +813,7 @@ module.exports = {
|
||||
const motionBlurEffect = extension
|
||||
.addEffect('MotionBlur')
|
||||
.setFullName(_('Motion Blur'))
|
||||
.setDescription(
|
||||
_('Blur the rendered image to give a feeling of speed.')
|
||||
)
|
||||
.setDescription(_('Blur the rendered image to give a feeling of speed.'))
|
||||
.markAsOnlyWorkingFor2D()
|
||||
.addIncludeFile('Extensions/Effects/pixi-filters/filter-motion-blur.js')
|
||||
.addIncludeFile('Extensions/Effects/motion-blur-pixi-filter.js');
|
||||
@@ -1174,7 +1169,9 @@ module.exports = {
|
||||
.setValue('0')
|
||||
.setLabel(_('Elapsed time'))
|
||||
.setType('number')
|
||||
.setDescription('It can be set back to 0 to play the shockwave animation again.');
|
||||
.setDescription(
|
||||
'It can be set back to 0 to play the shockwave animation again.'
|
||||
);
|
||||
shockwaveEffectProperties
|
||||
.getOrCreate('speed')
|
||||
.setValue('500')
|
||||
@@ -1311,10 +1308,7 @@ module.exports = {
|
||||
|
||||
return extension;
|
||||
},
|
||||
runExtensionSanityTests: function (
|
||||
gd /*: libGDevelop */,
|
||||
extension /*: gdPlatformExtension*/
|
||||
) {
|
||||
runExtensionSanityTests: function (gd, extension) {
|
||||
return [];
|
||||
},
|
||||
};
|
||||
|
@@ -1,4 +1,5 @@
|
||||
// @flow
|
||||
//@ts-check
|
||||
/// <reference path="../JsExtensionTypes.d.ts" />
|
||||
/**
|
||||
* This is a declaration of an extension for GDevelop 5.
|
||||
*
|
||||
@@ -12,18 +13,9 @@
|
||||
* More information on https://github.com/4ian/GDevelop/blob/master/newIDE/README-extensions.md
|
||||
*/
|
||||
|
||||
/*::
|
||||
// Import types to allow Flow to do static type checking on this file.
|
||||
// Extensions declaration are typed using Flow (like the editor), but the files
|
||||
// for the game engine are checked with TypeScript annotations.
|
||||
import { type ObjectsRenderingService, type ObjectsEditorService } from '../JsExtensionTypes.flow.js'
|
||||
*/
|
||||
|
||||
/** @type {ExtensionModule} */
|
||||
module.exports = {
|
||||
createExtension: function (
|
||||
_ /*: (string) => string */,
|
||||
gd /*: libGDevelop */
|
||||
) {
|
||||
createExtension: function (_, gd) {
|
||||
const extension = new gd.PlatformExtension();
|
||||
extension.setExtensionInformation(
|
||||
'MyDummyExtension',
|
||||
@@ -153,7 +145,6 @@ module.exports = {
|
||||
// Everything that is stored inside the behavior is in "behaviorContent" and is automatically
|
||||
// saved/loaded to JSON.
|
||||
var dummyBehavior = new gd.BehaviorJsImplementation();
|
||||
// $FlowExpectedError - ignore Flow warning as we're creating a behavior
|
||||
dummyBehavior.updateProperty = function (
|
||||
behaviorContent,
|
||||
propertyName,
|
||||
@@ -170,7 +161,6 @@ module.exports = {
|
||||
|
||||
return false;
|
||||
};
|
||||
// $FlowExpectedError - ignore Flow warning as we're creating a behavior
|
||||
dummyBehavior.getProperties = function (behaviorContent) {
|
||||
var behaviorProperties = new gd.MapStringPropertyDescriptor();
|
||||
|
||||
@@ -187,7 +177,6 @@ module.exports = {
|
||||
|
||||
return behaviorProperties;
|
||||
};
|
||||
// $FlowExpectedError - ignore Flow warning as we're creating a behavior
|
||||
dummyBehavior.initializeContent = function (behaviorContent) {
|
||||
behaviorContent.setStringAttribute('property1', 'Initial value 1');
|
||||
behaviorContent.setBoolAttribute('property2', true);
|
||||
@@ -201,6 +190,7 @@ module.exports = {
|
||||
'',
|
||||
'CppPlatform/Extensions/topdownmovementicon.png',
|
||||
'DummyBehavior',
|
||||
//@ts-ignore The class hierarchy is incorrect leading to a type error, but this is valid.
|
||||
dummyBehavior,
|
||||
new gd.BehaviorsSharedData()
|
||||
)
|
||||
@@ -215,7 +205,6 @@ module.exports = {
|
||||
// Create a new gd.BehaviorSharedDataJsImplementation object and implement the methods
|
||||
// that are called to get and set the properties of the shared data.
|
||||
var dummyBehaviorWithSharedData = new gd.BehaviorJsImplementation();
|
||||
// $FlowExpectedError - ignore Flow warning as we're creating a behavior
|
||||
dummyBehaviorWithSharedData.updateProperty = function (
|
||||
behaviorContent,
|
||||
propertyName,
|
||||
@@ -228,7 +217,6 @@ module.exports = {
|
||||
|
||||
return false;
|
||||
};
|
||||
// $FlowExpectedError - ignore Flow warning as we're creating a behavior
|
||||
dummyBehaviorWithSharedData.getProperties = function (behaviorContent) {
|
||||
var behaviorProperties = new gd.MapStringPropertyDescriptor();
|
||||
|
||||
@@ -238,13 +226,11 @@ module.exports = {
|
||||
|
||||
return behaviorProperties;
|
||||
};
|
||||
// $FlowExpectedError - ignore Flow warning as we're creating a behavior
|
||||
dummyBehaviorWithSharedData.initializeContent = function (behaviorContent) {
|
||||
behaviorContent.setStringAttribute('property1', 'Initial value 1');
|
||||
};
|
||||
|
||||
var sharedData = new gd.BehaviorSharedDataJsImplementation();
|
||||
// $FlowExpectedError - ignore Flow warning as we're creating a behavior
|
||||
sharedData.updateProperty = function (
|
||||
sharedContent,
|
||||
propertyName,
|
||||
@@ -257,7 +243,6 @@ module.exports = {
|
||||
|
||||
return false;
|
||||
};
|
||||
// $FlowExpectedError - ignore Flow warning as we're creating a behavior
|
||||
sharedData.getProperties = function (sharedContent) {
|
||||
var sharedProperties = new gd.MapStringPropertyDescriptor();
|
||||
|
||||
@@ -267,7 +252,6 @@ module.exports = {
|
||||
|
||||
return sharedProperties;
|
||||
};
|
||||
// $FlowExpectedError - ignore Flow warning as we're creating a behavior
|
||||
sharedData.initializeContent = function (behaviorContent) {
|
||||
behaviorContent.setStringAttribute(
|
||||
'sharedProperty1',
|
||||
@@ -284,6 +268,7 @@ module.exports = {
|
||||
'',
|
||||
'CppPlatform/Extensions/topdownmovementicon.png',
|
||||
'DummyBehaviorWithSharedData',
|
||||
//@ts-ignore The class hierarchy is incorrect leading to a type error, but this is valid.
|
||||
dummyBehaviorWithSharedData,
|
||||
sharedData
|
||||
)
|
||||
@@ -302,7 +287,6 @@ module.exports = {
|
||||
// Everything that is stored inside the object is in "content" and is automatically
|
||||
// saved/loaded to JSON.
|
||||
var dummyObject = new gd.ObjectJsImplementation();
|
||||
// $FlowExpectedError - ignore Flow warning as we're creating an object
|
||||
dummyObject.updateProperty = function (
|
||||
objectContent,
|
||||
propertyName,
|
||||
@@ -327,7 +311,6 @@ module.exports = {
|
||||
|
||||
return false;
|
||||
};
|
||||
// $FlowExpectedError - ignore Flow warning as we're creating an object
|
||||
dummyObject.getProperties = function (objectContent) {
|
||||
var objectProperties = new gd.MapStringPropertyDescriptor();
|
||||
|
||||
@@ -362,7 +345,6 @@ module.exports = {
|
||||
})
|
||||
);
|
||||
|
||||
// $FlowExpectedError - ignore Flow warning as we're creating an object
|
||||
dummyObject.updateInitialInstanceProperty = function (
|
||||
objectContent,
|
||||
instance,
|
||||
@@ -382,7 +364,6 @@ module.exports = {
|
||||
|
||||
return false;
|
||||
};
|
||||
// $FlowExpectedError - ignore Flow warning as we're creating an object
|
||||
dummyObject.getInitialInstanceProperties = function (
|
||||
content,
|
||||
instance,
|
||||
@@ -446,10 +427,7 @@ module.exports = {
|
||||
* But it is recommended to create tests for the behaviors/objects properties you created
|
||||
* to avoid mistakes.
|
||||
*/
|
||||
runExtensionSanityTests: function (
|
||||
gd /*: libGDevelop */,
|
||||
extension /*: gdPlatformExtension*/
|
||||
) {
|
||||
runExtensionSanityTests: function (gd, extension) {
|
||||
const dummyBehavior = extension
|
||||
.getBehaviorMetadata('MyDummyExtension::DummyBehavior')
|
||||
.get();
|
||||
@@ -474,9 +452,7 @@ module.exports = {
|
||||
*
|
||||
* ℹ️ Run `node import-GDJS-Runtime.js` (in newIDE/app/scripts) if you make any change.
|
||||
*/
|
||||
registerEditorConfigurations: function (
|
||||
objectsEditorService /*: ObjectsEditorService */
|
||||
) {
|
||||
registerEditorConfigurations: function (objectsEditorService) {
|
||||
objectsEditorService.registerEditorConfiguration(
|
||||
'MyDummyExtension::DummyObject',
|
||||
objectsEditorService.getDefaultObjectJsImplementationPropertiesEditor({
|
||||
@@ -489,9 +465,7 @@ module.exports = {
|
||||
*
|
||||
* ℹ️ Run `node import-GDJS-Runtime.js` (in newIDE/app/scripts) if you make any change.
|
||||
*/
|
||||
registerInstanceRenderers: function (
|
||||
objectsRenderingService /*: ObjectsRenderingService */
|
||||
) {
|
||||
registerInstanceRenderers: function (objectsRenderingService) {
|
||||
const RenderedInstance = objectsRenderingService.RenderedInstance;
|
||||
const PIXI = objectsRenderingService.PIXI;
|
||||
|
||||
|
@@ -1,4 +1,5 @@
|
||||
// @flow
|
||||
//@ts-check
|
||||
/// <reference path="../JsExtensionTypes.d.ts" />
|
||||
/**
|
||||
* This is a declaration of an extension for GDevelop 5.
|
||||
*
|
||||
@@ -12,368 +13,414 @@
|
||||
* More information on https://github.com/4ian/GDevelop/blob/master/newIDE/README-extensions.md
|
||||
*/
|
||||
|
||||
/*::
|
||||
// Import types to allow Flow to do static type checking on this file.
|
||||
// Extensions declaration are typed using Flow (like the editor), but the files
|
||||
// for the game engine are checked with TypeScript annotations.
|
||||
import { type ObjectsRenderingService, type ObjectsEditorService } from '../JsExtensionTypes.flow.js'
|
||||
*/
|
||||
|
||||
/** @type {ExtensionModule} */
|
||||
module.exports = {
|
||||
createExtension: function(_/*: (string) => string */, gd/*: libGDevelop */) {
|
||||
createExtension: function (_, gd) {
|
||||
const extension = new gd.PlatformExtension();
|
||||
extension
|
||||
.setExtensionInformation(
|
||||
"FacebookInstantGames",
|
||||
_("Facebook Instant Games"),
|
||||
'FacebookInstantGames',
|
||||
_('Facebook Instant Games'),
|
||||
_(
|
||||
"Allow your game to send scores and interact with the Facebook Instant Games platform."
|
||||
'Allow your game to send scores and interact with the Facebook Instant Games platform.'
|
||||
),
|
||||
"Florian Rival",
|
||||
"Open source (MIT License)"
|
||||
'Florian Rival',
|
||||
'Open source (MIT License)'
|
||||
)
|
||||
.setExtensionHelpPath("/publishing/publishing-to-facebook-instant-games")
|
||||
.setExtensionHelpPath('/publishing/publishing-to-facebook-instant-games')
|
||||
.setCategory('Third-party');
|
||||
extension.addInstructionOrExpressionGroupMetadata(_("Facebook Instant Games"))
|
||||
.setIcon("JsPlatform/Extensions/facebookicon32.png");
|
||||
extension
|
||||
.addInstructionOrExpressionGroupMetadata(_('Facebook Instant Games'))
|
||||
.setIcon('JsPlatform/Extensions/facebookicon32.png');
|
||||
|
||||
extension
|
||||
.addAction(
|
||||
"SavePlayerData",
|
||||
_("Save player data"),
|
||||
'SavePlayerData',
|
||||
_('Save player data'),
|
||||
_(
|
||||
"Save the content of the given scene variable in the player data, stored on Facebook Instant Games servers"
|
||||
'Save the content of the given scene variable in the player data, stored on Facebook Instant Games servers'
|
||||
),
|
||||
_(
|
||||
"Save the content of _PARAM1_ in key _PARAM0_ of player data (store success message in _PARAM2_ or error in _PARAM3_)"
|
||||
'Save the content of _PARAM1_ in key _PARAM0_ of player data (store success message in _PARAM2_ or error in _PARAM3_)'
|
||||
),
|
||||
_("Player data"),
|
||||
"JsPlatform/Extensions/facebookicon32.png",
|
||||
"JsPlatform/Extensions/facebookicon32.png"
|
||||
_('Player data'),
|
||||
'JsPlatform/Extensions/facebookicon32.png',
|
||||
'JsPlatform/Extensions/facebookicon32.png'
|
||||
)
|
||||
.addParameter("string", 'Data key name (e.g: "Lives")', "", false)
|
||||
.addParameter("scenevar", "Scene variable with the content to save", "", false)
|
||||
.addParameter('string', 'Data key name (e.g: "Lives")', '', false)
|
||||
.addParameter(
|
||||
"scenevar",
|
||||
_("Variable where to store the success message (optional)"),
|
||||
"",
|
||||
true
|
||||
)
|
||||
.addParameter(
|
||||
"scenevar",
|
||||
_("Variable where to store the error message (optional, if an error occurs)"),
|
||||
"",
|
||||
true
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile(
|
||||
"Extensions/FacebookInstantGames/facebookinstantgamestools.js"
|
||||
)
|
||||
.setFunctionName("gdjs.evtTools.facebookInstantGames.setPlayerData");
|
||||
|
||||
extension
|
||||
.addAction(
|
||||
"LoadPlayerData",
|
||||
_("Load player data"),
|
||||
_("Load the player data with the given key in a variable"),
|
||||
_(
|
||||
"Load player data with key _PARAM0_ in _PARAM1_ (or error in _PARAM2_)"
|
||||
),
|
||||
_("Player data"),
|
||||
"JsPlatform/Extensions/facebookicon32.png",
|
||||
"JsPlatform/Extensions/facebookicon32.png"
|
||||
)
|
||||
.addParameter("string", _('Data key name (e.g: "Lives")'), "", false)
|
||||
.addParameter(
|
||||
"scenevar",
|
||||
_("Variable where to store loaded data"),
|
||||
"",
|
||||
'scenevar',
|
||||
'Scene variable with the content to save',
|
||||
'',
|
||||
false
|
||||
)
|
||||
.addParameter(
|
||||
"scenevar",
|
||||
_("Variable where to store the error message (optional, if an error occurs)"),
|
||||
"",
|
||||
'scenevar',
|
||||
_('Variable where to store the success message (optional)'),
|
||||
'',
|
||||
true
|
||||
)
|
||||
.addParameter(
|
||||
'scenevar',
|
||||
_(
|
||||
'Variable where to store the error message (optional, if an error occurs)'
|
||||
),
|
||||
'',
|
||||
true
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile(
|
||||
"Extensions/FacebookInstantGames/facebookinstantgamestools.js"
|
||||
'Extensions/FacebookInstantGames/facebookinstantgamestools.js'
|
||||
)
|
||||
.setFunctionName("gdjs.evtTools.facebookInstantGames.loadPlayerData");
|
||||
.setFunctionName('gdjs.evtTools.facebookInstantGames.setPlayerData');
|
||||
|
||||
extension
|
||||
.addAction(
|
||||
"SavePlayerScore",
|
||||
_("Save player score"),
|
||||
'LoadPlayerData',
|
||||
_('Load player data'),
|
||||
_('Load the player data with the given key in a variable'),
|
||||
_(
|
||||
"Save the score, and optionally the content of the given variable in the player score, for the given metadata."
|
||||
'Load player data with key _PARAM0_ in _PARAM1_ (or error in _PARAM2_)'
|
||||
),
|
||||
_(
|
||||
"In leaderboard _PARAM0_, save score _PARAM1_ for the player and extra data from _PARAM2_ (store success message in _PARAM3_ or error in _PARAM4_)"
|
||||
),
|
||||
_("Leaderboards"),
|
||||
"JsPlatform/Extensions/facebookicon32.png",
|
||||
"JsPlatform/Extensions/facebookicon32.png"
|
||||
_('Player data'),
|
||||
'JsPlatform/Extensions/facebookicon32.png',
|
||||
'JsPlatform/Extensions/facebookicon32.png'
|
||||
)
|
||||
.addParameter('string', _('Data key name (e.g: "Lives")'), '', false)
|
||||
.addParameter(
|
||||
'scenevar',
|
||||
_('Variable where to store loaded data'),
|
||||
'',
|
||||
false
|
||||
)
|
||||
.addParameter(
|
||||
"string",
|
||||
'scenevar',
|
||||
_(
|
||||
'Variable where to store the error message (optional, if an error occurs)'
|
||||
),
|
||||
'',
|
||||
true
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile(
|
||||
'Extensions/FacebookInstantGames/facebookinstantgamestools.js'
|
||||
)
|
||||
.setFunctionName('gdjs.evtTools.facebookInstantGames.loadPlayerData');
|
||||
|
||||
extension
|
||||
.addAction(
|
||||
'SavePlayerScore',
|
||||
_('Save player score'),
|
||||
_(
|
||||
'Save the score, and optionally the content of the given variable in the player score, for the given metadata.'
|
||||
),
|
||||
_(
|
||||
'In leaderboard _PARAM0_, save score _PARAM1_ for the player and extra data from _PARAM2_ (store success message in _PARAM3_ or error in _PARAM4_)'
|
||||
),
|
||||
_('Leaderboards'),
|
||||
'JsPlatform/Extensions/facebookicon32.png',
|
||||
'JsPlatform/Extensions/facebookicon32.png'
|
||||
)
|
||||
.addParameter(
|
||||
'string',
|
||||
'Leaderboard name (e.g: "PlayersBestTimes")',
|
||||
"",
|
||||
'',
|
||||
false
|
||||
)
|
||||
.addParameter("expression", "Score to register for the player", "", false)
|
||||
.addParameter('expression', 'Score to register for the player', '', false)
|
||||
.addParameter(
|
||||
"scenevar",
|
||||
_("Optional variable with metadata to save"),
|
||||
"",
|
||||
'scenevar',
|
||||
_('Optional variable with metadata to save'),
|
||||
'',
|
||||
true
|
||||
)
|
||||
.addParameter(
|
||||
"scenevar",
|
||||
_("Variable where to store the success message (optional)"),
|
||||
"",
|
||||
'scenevar',
|
||||
_('Variable where to store the success message (optional)'),
|
||||
'',
|
||||
true
|
||||
)
|
||||
.addParameter(
|
||||
"scenevar",
|
||||
_("Variable where to store the error message (optional, if an error occurs)"),
|
||||
"",
|
||||
true
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile(
|
||||
"Extensions/FacebookInstantGames/facebookinstantgamestools.js"
|
||||
)
|
||||
.setFunctionName("gdjs.evtTools.facebookInstantGames.setPlayerScore");
|
||||
|
||||
extension
|
||||
.addAction(
|
||||
"LoadPlayerEntry",
|
||||
_("Load player entry"),
|
||||
_("Load the player entry in the given leaderboard"),
|
||||
'scenevar',
|
||||
_(
|
||||
"Load player entry from leaderboard _PARAM0_. Set rank in _PARAM1_, score in _PARAM2_ (extra data if any in _PARAM3_ and error in _PARAM4_)"
|
||||
'Variable where to store the error message (optional, if an error occurs)'
|
||||
),
|
||||
_("Leaderboards"),
|
||||
"JsPlatform/Extensions/facebookicon32.png",
|
||||
"JsPlatform/Extensions/facebookicon32.png"
|
||||
'',
|
||||
true
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile(
|
||||
'Extensions/FacebookInstantGames/facebookinstantgamestools.js'
|
||||
)
|
||||
.setFunctionName('gdjs.evtTools.facebookInstantGames.setPlayerScore');
|
||||
|
||||
extension
|
||||
.addAction(
|
||||
'LoadPlayerEntry',
|
||||
_('Load player entry'),
|
||||
_('Load the player entry in the given leaderboard'),
|
||||
_(
|
||||
'Load player entry from leaderboard _PARAM0_. Set rank in _PARAM1_, score in _PARAM2_ (extra data if any in _PARAM3_ and error in _PARAM4_)'
|
||||
),
|
||||
_('Leaderboards'),
|
||||
'JsPlatform/Extensions/facebookicon32.png',
|
||||
'JsPlatform/Extensions/facebookicon32.png'
|
||||
)
|
||||
.addParameter(
|
||||
"string",
|
||||
'string',
|
||||
_('Leaderboard name (e.g: "PlayersBestTimes")'),
|
||||
"",
|
||||
'',
|
||||
false
|
||||
)
|
||||
.addParameter(
|
||||
"scenevar",
|
||||
_("Variable where to store the player rank (of -1 if not ranked)"),
|
||||
"",
|
||||
'scenevar',
|
||||
_('Variable where to store the player rank (of -1 if not ranked)'),
|
||||
'',
|
||||
true
|
||||
)
|
||||
.addParameter(
|
||||
"scenevar",
|
||||
_("Variable where to store the player score (of -1 if no score)"),
|
||||
"",
|
||||
'scenevar',
|
||||
_('Variable where to store the player score (of -1 if no score)'),
|
||||
'',
|
||||
true
|
||||
)
|
||||
.addParameter(
|
||||
"scenevar",
|
||||
_("Variable where to store extra data (if any)"),
|
||||
"",
|
||||
'scenevar',
|
||||
_('Variable where to store extra data (if any)'),
|
||||
'',
|
||||
true
|
||||
)
|
||||
.addParameter(
|
||||
"scenevar",
|
||||
_("Variable where to store the error message (optional, if an error occurs)"),
|
||||
"",
|
||||
'scenevar',
|
||||
_(
|
||||
'Variable where to store the error message (optional, if an error occurs)'
|
||||
),
|
||||
'',
|
||||
true
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile(
|
||||
"Extensions/FacebookInstantGames/facebookinstantgamestools.js"
|
||||
'Extensions/FacebookInstantGames/facebookinstantgamestools.js'
|
||||
)
|
||||
.setFunctionName("gdjs.evtTools.facebookInstantGames.getPlayerEntry");
|
||||
.setFunctionName('gdjs.evtTools.facebookInstantGames.getPlayerEntry');
|
||||
|
||||
extension
|
||||
.addCondition(
|
||||
"AreAdsSupported",
|
||||
_("Check if ads are supported"),
|
||||
_("Check if showing ads is supported on this device (only mobile phones can show ads)"),
|
||||
_("Ads can be shown on this device"),
|
||||
_("Ads"),
|
||||
"JsPlatform/Extensions/facebookicon32.png",
|
||||
"JsPlatform/Extensions/facebookicon32.png"
|
||||
'AreAdsSupported',
|
||||
_('Check if ads are supported'),
|
||||
_(
|
||||
'Check if showing ads is supported on this device (only mobile phones can show ads)'
|
||||
),
|
||||
_('Ads can be shown on this device'),
|
||||
_('Ads'),
|
||||
'JsPlatform/Extensions/facebookicon32.png',
|
||||
'JsPlatform/Extensions/facebookicon32.png'
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile(
|
||||
"Extensions/FacebookInstantGames/facebookinstantgamestools.js"
|
||||
'Extensions/FacebookInstantGames/facebookinstantgamestools.js'
|
||||
)
|
||||
.setFunctionName("gdjs.evtTools.facebookInstantGames.areAdsSupported");
|
||||
.setFunctionName('gdjs.evtTools.facebookInstantGames.areAdsSupported');
|
||||
|
||||
extension
|
||||
.addCondition(
|
||||
"IsInterstitialAdReady",
|
||||
_("Is the interstitial ad ready"),
|
||||
_("Check if the interstitial ad requested from Facebook is loaded and ready to be shown."),
|
||||
_("The interstitial ad is loaded and ready to be shown"),
|
||||
_("Ads"),
|
||||
"JsPlatform/Extensions/facebookicon32.png",
|
||||
"JsPlatform/Extensions/facebookicon32.png"
|
||||
'IsInterstitialAdReady',
|
||||
_('Is the interstitial ad ready'),
|
||||
_(
|
||||
'Check if the interstitial ad requested from Facebook is loaded and ready to be shown.'
|
||||
),
|
||||
_('The interstitial ad is loaded and ready to be shown'),
|
||||
_('Ads'),
|
||||
'JsPlatform/Extensions/facebookicon32.png',
|
||||
'JsPlatform/Extensions/facebookicon32.png'
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile(
|
||||
"Extensions/FacebookInstantGames/facebookinstantgamestools.js"
|
||||
'Extensions/FacebookInstantGames/facebookinstantgamestools.js'
|
||||
)
|
||||
.setFunctionName("gdjs.evtTools.facebookInstantGames.isInterstitialAdReady");
|
||||
.setFunctionName(
|
||||
'gdjs.evtTools.facebookInstantGames.isInterstitialAdReady'
|
||||
);
|
||||
|
||||
extension
|
||||
.addAction(
|
||||
"LoadInterstitialAd",
|
||||
_("Load and prepare an interstitial ad"),
|
||||
_("Request and load an interstitial ad from Facebook, so that it is ready to be shown."),
|
||||
_("Request and load an interstitial ad from Facebook (ad placement id: _PARAM0_, error in _PARAM1_)"),
|
||||
_("Ads"),
|
||||
"JsPlatform/Extensions/facebookicon32.png",
|
||||
"JsPlatform/Extensions/facebookicon32.png"
|
||||
'LoadInterstitialAd',
|
||||
_('Load and prepare an interstitial ad'),
|
||||
_(
|
||||
'Request and load an interstitial ad from Facebook, so that it is ready to be shown.'
|
||||
),
|
||||
_(
|
||||
'Request and load an interstitial ad from Facebook (ad placement id: _PARAM0_, error in _PARAM1_)'
|
||||
),
|
||||
_('Ads'),
|
||||
'JsPlatform/Extensions/facebookicon32.png',
|
||||
'JsPlatform/Extensions/facebookicon32.png'
|
||||
)
|
||||
.addParameter(
|
||||
"string",
|
||||
_("The Ad Placement id (can be found while setting up the ad on Facebook)"),
|
||||
"",
|
||||
'string',
|
||||
_(
|
||||
'The Ad Placement id (can be found while setting up the ad on Facebook)'
|
||||
),
|
||||
'',
|
||||
false
|
||||
)
|
||||
.addParameter(
|
||||
"scenevar",
|
||||
_("Variable where to store the error message (optional, if an error occurs)"),
|
||||
"",
|
||||
'scenevar',
|
||||
_(
|
||||
'Variable where to store the error message (optional, if an error occurs)'
|
||||
),
|
||||
'',
|
||||
true
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile(
|
||||
"Extensions/FacebookInstantGames/facebookinstantgamestools.js"
|
||||
'Extensions/FacebookInstantGames/facebookinstantgamestools.js'
|
||||
)
|
||||
.setFunctionName("gdjs.evtTools.facebookInstantGames.loadInterstitialAd");
|
||||
.setFunctionName('gdjs.evtTools.facebookInstantGames.loadInterstitialAd');
|
||||
|
||||
extension
|
||||
.addAction(
|
||||
"ShowInterstitialAd",
|
||||
_("Show the loaded interstitial ad"),
|
||||
_("Show the interstitial ad previously loaded in memory. This won't work if you did not load the interstitial before."),
|
||||
_("Show the interstitial ad previously loaded in memory (if any error, store it in _PARAM0_)"),
|
||||
_("Ads"),
|
||||
"JsPlatform/Extensions/facebookicon32.png",
|
||||
"JsPlatform/Extensions/facebookicon32.png"
|
||||
'ShowInterstitialAd',
|
||||
_('Show the loaded interstitial ad'),
|
||||
_(
|
||||
"Show the interstitial ad previously loaded in memory. This won't work if you did not load the interstitial before."
|
||||
),
|
||||
_(
|
||||
'Show the interstitial ad previously loaded in memory (if any error, store it in _PARAM0_)'
|
||||
),
|
||||
_('Ads'),
|
||||
'JsPlatform/Extensions/facebookicon32.png',
|
||||
'JsPlatform/Extensions/facebookicon32.png'
|
||||
)
|
||||
.addParameter(
|
||||
"scenevar",
|
||||
_("Variable where to store the error message (optional, if an error occurs)"),
|
||||
"",
|
||||
'scenevar',
|
||||
_(
|
||||
'Variable where to store the error message (optional, if an error occurs)'
|
||||
),
|
||||
'',
|
||||
true
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile(
|
||||
"Extensions/FacebookInstantGames/facebookinstantgamestools.js"
|
||||
'Extensions/FacebookInstantGames/facebookinstantgamestools.js'
|
||||
)
|
||||
.setFunctionName("gdjs.evtTools.facebookInstantGames.showInterstitialAd");
|
||||
.setFunctionName('gdjs.evtTools.facebookInstantGames.showInterstitialAd');
|
||||
|
||||
extension
|
||||
.addCondition(
|
||||
"IsRewardedVideoReady",
|
||||
_("Is the rewarded video ready"),
|
||||
_("Check if the rewarded video requested from Facebook is loaded and ready to be shown."),
|
||||
_("The rewarded video is loaded and ready to be shown"),
|
||||
_("Ads"),
|
||||
"JsPlatform/Extensions/facebookicon32.png",
|
||||
"JsPlatform/Extensions/facebookicon32.png"
|
||||
'IsRewardedVideoReady',
|
||||
_('Is the rewarded video ready'),
|
||||
_(
|
||||
'Check if the rewarded video requested from Facebook is loaded and ready to be shown.'
|
||||
),
|
||||
_('The rewarded video is loaded and ready to be shown'),
|
||||
_('Ads'),
|
||||
'JsPlatform/Extensions/facebookicon32.png',
|
||||
'JsPlatform/Extensions/facebookicon32.png'
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile(
|
||||
"Extensions/FacebookInstantGames/facebookinstantgamestools.js"
|
||||
'Extensions/FacebookInstantGames/facebookinstantgamestools.js'
|
||||
)
|
||||
.setFunctionName("gdjs.evtTools.facebookInstantGames.isRewardedVideoReady");
|
||||
.setFunctionName(
|
||||
'gdjs.evtTools.facebookInstantGames.isRewardedVideoReady'
|
||||
);
|
||||
|
||||
extension
|
||||
.addAction(
|
||||
"LoadRewardedVideo",
|
||||
_("Load and prepare a rewarded video"),
|
||||
_("Request and load a rewarded video from Facebook, so that it is ready to be shown."),
|
||||
_("Request and load a rewarded video from Facebook (ad placement id: _PARAM0_, error in _PARAM1_)"),
|
||||
_("Ads"),
|
||||
"JsPlatform/Extensions/facebookicon32.png",
|
||||
"JsPlatform/Extensions/facebookicon32.png"
|
||||
'LoadRewardedVideo',
|
||||
_('Load and prepare a rewarded video'),
|
||||
_(
|
||||
'Request and load a rewarded video from Facebook, so that it is ready to be shown.'
|
||||
),
|
||||
_(
|
||||
'Request and load a rewarded video from Facebook (ad placement id: _PARAM0_, error in _PARAM1_)'
|
||||
),
|
||||
_('Ads'),
|
||||
'JsPlatform/Extensions/facebookicon32.png',
|
||||
'JsPlatform/Extensions/facebookicon32.png'
|
||||
)
|
||||
.addParameter(
|
||||
"string",
|
||||
_("The Ad Placement id (can be found while setting up the ad on Facebook)"),
|
||||
"",
|
||||
'string',
|
||||
_(
|
||||
'The Ad Placement id (can be found while setting up the ad on Facebook)'
|
||||
),
|
||||
'',
|
||||
false
|
||||
)
|
||||
.addParameter(
|
||||
"scenevar",
|
||||
_("Variable where to store the error message (optional, if an error occurs)"),
|
||||
"",
|
||||
'scenevar',
|
||||
_(
|
||||
'Variable where to store the error message (optional, if an error occurs)'
|
||||
),
|
||||
'',
|
||||
true
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile(
|
||||
"Extensions/FacebookInstantGames/facebookinstantgamestools.js"
|
||||
'Extensions/FacebookInstantGames/facebookinstantgamestools.js'
|
||||
)
|
||||
.setFunctionName("gdjs.evtTools.facebookInstantGames.loadRewardedVideo");
|
||||
.setFunctionName('gdjs.evtTools.facebookInstantGames.loadRewardedVideo');
|
||||
|
||||
extension
|
||||
.addAction(
|
||||
"ShowRewardedVideo",
|
||||
_("Show the loaded rewarded video"),
|
||||
_("Show the rewarded video previously loaded in memory. This won't work if you did not load the video before."),
|
||||
_("Show the rewarded video previously loaded in memory (if any error, store it in _PARAM0_)"),
|
||||
_("Ads"),
|
||||
"JsPlatform/Extensions/facebookicon32.png",
|
||||
"JsPlatform/Extensions/facebookicon32.png"
|
||||
'ShowRewardedVideo',
|
||||
_('Show the loaded rewarded video'),
|
||||
_(
|
||||
"Show the rewarded video previously loaded in memory. This won't work if you did not load the video before."
|
||||
),
|
||||
_(
|
||||
'Show the rewarded video previously loaded in memory (if any error, store it in _PARAM0_)'
|
||||
),
|
||||
_('Ads'),
|
||||
'JsPlatform/Extensions/facebookicon32.png',
|
||||
'JsPlatform/Extensions/facebookicon32.png'
|
||||
)
|
||||
.addParameter(
|
||||
"scenevar",
|
||||
_("Variable where to store the error message (optional, if an error occurs)"),
|
||||
"",
|
||||
'scenevar',
|
||||
_(
|
||||
'Variable where to store the error message (optional, if an error occurs)'
|
||||
),
|
||||
'',
|
||||
true
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile(
|
||||
"Extensions/FacebookInstantGames/facebookinstantgamestools.js"
|
||||
'Extensions/FacebookInstantGames/facebookinstantgamestools.js'
|
||||
)
|
||||
.setFunctionName("gdjs.evtTools.facebookInstantGames.showRewardedVideo");
|
||||
.setFunctionName('gdjs.evtTools.facebookInstantGames.showRewardedVideo');
|
||||
|
||||
extension
|
||||
.addStrExpression(
|
||||
"PlayerId",
|
||||
_("Player identifier"),
|
||||
_("Get the player unique identifier"),
|
||||
'PlayerId',
|
||||
_('Player identifier'),
|
||||
_('Get the player unique identifier'),
|
||||
'',
|
||||
"JsPlatform/Extensions/facebookicon32.png"
|
||||
'JsPlatform/Extensions/facebookicon32.png'
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile(
|
||||
"Extensions/FacebookInstantGames/facebookinstantgamestools.js"
|
||||
'Extensions/FacebookInstantGames/facebookinstantgamestools.js'
|
||||
)
|
||||
.setFunctionName("gdjs.evtTools.facebookInstantGames.getPlayerId");
|
||||
.setFunctionName('gdjs.evtTools.facebookInstantGames.getPlayerId');
|
||||
|
||||
extension
|
||||
.addStrExpression(
|
||||
"PlayerName",
|
||||
_("Player name"),
|
||||
_("Get the player name"),
|
||||
'PlayerName',
|
||||
_('Player name'),
|
||||
_('Get the player name'),
|
||||
'',
|
||||
"JsPlatform/Extensions/facebookicon32.png"
|
||||
'JsPlatform/Extensions/facebookicon32.png'
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile(
|
||||
"Extensions/FacebookInstantGames/facebookinstantgamestools.js"
|
||||
'Extensions/FacebookInstantGames/facebookinstantgamestools.js'
|
||||
)
|
||||
.setFunctionName("gdjs.evtTools.facebookInstantGames.getPlayerName");
|
||||
.setFunctionName('gdjs.evtTools.facebookInstantGames.getPlayerName');
|
||||
|
||||
return extension;
|
||||
},
|
||||
runExtensionSanityTests: function(gd /*: libGDevelop */, extension /*: gdPlatformExtension*/) {
|
||||
runExtensionSanityTests: function (gd, extension) {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
};
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,5 @@
|
||||
// @flow
|
||||
//@ts-check
|
||||
/// <reference path="../JsExtensionTypes.d.ts" />
|
||||
/**
|
||||
* This is a declaration of an extension for GDevelop 5.
|
||||
*
|
||||
@@ -11,11 +12,10 @@
|
||||
*
|
||||
* More information on https://github.com/4ian/GDevelop/blob/master/newIDE/README-extensions.md
|
||||
*/
|
||||
|
||||
/** @type {ExtensionModule} */
|
||||
module.exports = {
|
||||
createExtension: function (
|
||||
_ /*: (string) => string */,
|
||||
gd /*: libGDevelop */
|
||||
) {
|
||||
createExtension: function (_, gd) {
|
||||
const extension = new gd.PlatformExtension();
|
||||
|
||||
extension
|
||||
@@ -2314,10 +2314,7 @@ module.exports = {
|
||||
|
||||
return extension;
|
||||
},
|
||||
runExtensionSanityTests: function (
|
||||
gd /*: libGDevelop */,
|
||||
extension /*: gdPlatformExtension */
|
||||
) {
|
||||
runExtensionSanityTests: function (gd, extension) {
|
||||
return [];
|
||||
},
|
||||
};
|
||||
|
225
Extensions/JsExtensionTypes.d.ts
vendored
Normal file
225
Extensions/JsExtensionTypes.d.ts
vendored
Normal file
@@ -0,0 +1,225 @@
|
||||
type GDNamespace = typeof import('../GDevelop.js/types');
|
||||
|
||||
// This is necessary for typescript to interpret the identifier PIXI as a namespace
|
||||
// in this file and merge it with the other namespace declarations.
|
||||
declare namespace PIXI {}
|
||||
|
||||
/**
|
||||
* RenderedInstance is the base class used for creating 2D renderers of instances,
|
||||
* which display on the scene editor, using Pixi.js, the instance of an object (see InstancesEditor).
|
||||
*/
|
||||
class RenderedInstance {
|
||||
_project: gd.Project;
|
||||
_layout: gd.Layout;
|
||||
_instance: gd.InitialInstance;
|
||||
_associatedObjectConfiguration: gd.ObjectConfiguration;
|
||||
_pixiContainer: PIXI.Container;
|
||||
_pixiResourcesLoader: Class<PixiResourcesLoader>;
|
||||
_pixiObject: PIXI.DisplayObject;
|
||||
wasUsed: boolean;
|
||||
|
||||
constructor(
|
||||
project: gdProject,
|
||||
layout: gdLayout,
|
||||
instance: gdInitialInstance,
|
||||
associatedObjectConfiguration: gdObjectConfiguration,
|
||||
pixiContainer: PIXI.Container,
|
||||
pixiResourcesLoader: Class<PixiResourcesLoader>
|
||||
);
|
||||
|
||||
/**
|
||||
* Convert an angle from degrees to radians.
|
||||
*/
|
||||
static toRad(angleInDegrees: number): number;
|
||||
|
||||
/**
|
||||
* Called when the scene editor is rendered.
|
||||
*/
|
||||
update(): void;
|
||||
|
||||
getPixiObject(): PIXI.DisplayObject | null;
|
||||
|
||||
getInstance(): gd.InitialInstance;
|
||||
|
||||
/**
|
||||
* Called to notify the instance renderer that its associated instance was removed from
|
||||
* the scene. The PIXI object should probably be removed from the container: This is what
|
||||
* the default implementation of the method does.
|
||||
*/
|
||||
onRemovedFromScene(): void;
|
||||
|
||||
getOriginX(): number;
|
||||
|
||||
getOriginY(): number;
|
||||
|
||||
getCenterX(): number;
|
||||
|
||||
getCenterY(): number;
|
||||
|
||||
getCustomWidth(): number;
|
||||
|
||||
getCustomHeight(): number;
|
||||
|
||||
getWidth(): number;
|
||||
|
||||
getHeight(): number;
|
||||
|
||||
getDepth(): number;
|
||||
|
||||
/**
|
||||
* Return the width of the instance when the instance doesn't have a custom size.
|
||||
*/
|
||||
getDefaultWidth(): number;
|
||||
|
||||
/**
|
||||
* Return the height of the instance when the instance doesn't have a custom size.
|
||||
*/
|
||||
getDefaultHeight(): number;
|
||||
|
||||
getDefaultDepth(): number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rendered3DInstance is the base class used for creating 3D renderers of instances,
|
||||
* which display on the scene editor, using Three.js, the instance of an object (see InstancesEditor).
|
||||
* It can also display 2D artifacts on Pixi 2D plane (3D object shadow projected on the plane for instance).
|
||||
*/
|
||||
class Rendered3DInstance {
|
||||
_project: gdProject;
|
||||
_layout: gdLayout;
|
||||
_instance: gdInitialInstance;
|
||||
_associatedObjectConfiguration: gdObjectConfiguration;
|
||||
_pixiContainer: PIXI.Container;
|
||||
_threeGroup: THREE.Group;
|
||||
_pixiResourcesLoader: Class<PixiResourcesLoader>;
|
||||
_pixiObject: PIXI.DisplayObject;
|
||||
_threeObject: THREE.Object3D | null;
|
||||
wasUsed: boolean;
|
||||
|
||||
constructor(
|
||||
project: gdProject,
|
||||
layout: gdLayout,
|
||||
instance: gdInitialInstance,
|
||||
associatedObjectConfiguration: gdObjectConfiguration,
|
||||
pixiContainer: PIXI.Container,
|
||||
threeGroup: THREE.Group,
|
||||
pixiResourcesLoader: Class<PixiResourcesLoader>
|
||||
);
|
||||
|
||||
/**
|
||||
* Convert an angle from degrees to radians.
|
||||
*/
|
||||
static toRad(angleInDegrees: number): number;
|
||||
|
||||
/**
|
||||
* Called when the scene editor is rendered.
|
||||
*/
|
||||
update(): void;
|
||||
|
||||
getPixiObject(): PIXI.DisplayObject;
|
||||
|
||||
getThreeObject(): THREE.Object3D;
|
||||
|
||||
getInstance(): gd.InitialInstance;
|
||||
|
||||
/**
|
||||
* Called to notify the instance renderer that its associated instance was removed from
|
||||
* the scene. The PIXI object should probably be removed from the container: This is what
|
||||
* the default implementation of the method does.
|
||||
*/
|
||||
onRemovedFromScene(): void;
|
||||
|
||||
getOriginX(): number;
|
||||
|
||||
getOriginY(): number;
|
||||
|
||||
getCenterX(): number;
|
||||
|
||||
getCenterY(): number;
|
||||
|
||||
getWidth(): number;
|
||||
|
||||
getHeight(): number;
|
||||
|
||||
getDepth(): number;
|
||||
|
||||
/**
|
||||
* Return the width of the instance when the instance doesn't have a custom size.
|
||||
*/
|
||||
getDefaultWidth(): number;
|
||||
|
||||
/**
|
||||
* Return the height of the instance when the instance doesn't have a custom size.
|
||||
*/
|
||||
getDefaultHeight(): number;
|
||||
|
||||
/**
|
||||
* Return the depth of the instance when the instance doesn't have a custom size.
|
||||
*/
|
||||
getDefaultDepth(): number;
|
||||
}
|
||||
|
||||
declare type ObjectsRenderingService = {
|
||||
gd: GDNamespace;
|
||||
PIXI: PIXI;
|
||||
THREE: typeof import('../newIDE/app/node_modules/three');
|
||||
THREE_ADDONS: { SkeletonUtils: any };
|
||||
RenderedInstance: typeof RenderedInstance;
|
||||
Rendered3DInstance: typeof Rendered3DInstance;
|
||||
registerInstanceRenderer: (objectType: string, renderer: any) => void;
|
||||
registerInstance3DRenderer: (objectType: string, renderer: any) => void;
|
||||
requireModule: (dirname: string, moduleName: string) => any;
|
||||
getThumbnail: (
|
||||
project: gd.Project,
|
||||
objectConfiguration: gd.ObjectConfiguration
|
||||
) => string;
|
||||
rgbOrHexToHexNumber: (value: string) => number;
|
||||
registerClearCache: (clearCache: (_: any) => void) => void;
|
||||
};
|
||||
|
||||
declare type ObjectsEditorService = {
|
||||
registerEditorConfiguration: (
|
||||
objectType: string,
|
||||
editorConfiguration: any
|
||||
) => void;
|
||||
getDefaultObjectJsImplementationPropertiesEditor: ({
|
||||
helpPagePath: string,
|
||||
}) => any;
|
||||
};
|
||||
|
||||
declare type ExtensionModule = {
|
||||
createExtension: (
|
||||
_: (string) => string,
|
||||
gd: GDNamespace
|
||||
) => gd.PlatformExtension;
|
||||
/**
|
||||
* You can optionally add sanity tests that will check the basic working
|
||||
* of your extension behaviors/objects by instantiating behaviors/objects
|
||||
* and setting the property to a given value.
|
||||
*
|
||||
* If you don't have any tests, you can simply return an empty array.
|
||||
*
|
||||
* But it is recommended to create tests for the behaviors/objects properties you created
|
||||
* to avoid mistakes.
|
||||
*/
|
||||
runExtensionSanityTests: (
|
||||
gd: GDNamespace,
|
||||
extension: gd.PlatformExtension
|
||||
) => string[];
|
||||
/**
|
||||
* Register editors for objects.
|
||||
*
|
||||
* ℹ️ Run `node import-GDJS-Runtime.js` (in newIDE/app/scripts) if you make any change.
|
||||
*/
|
||||
registerEditorConfigurations?: (
|
||||
objectsEditorService: ObjectsEditorService
|
||||
) => void;
|
||||
/**
|
||||
* Register renderers for instance of objects on the scene editor.
|
||||
*
|
||||
* ℹ️ Run `node import-GDJS-Runtime.js` (in newIDE/app/scripts) if you make any change.
|
||||
*/
|
||||
registerInstanceRenderers?: (
|
||||
objectsRenderingService: ObjectsRenderingService
|
||||
) => void;
|
||||
};
|
@@ -1,35 +0,0 @@
|
||||
// @flow
|
||||
|
||||
/**
|
||||
* @file This file contains the (Flow) types that are used in the JavaScript
|
||||
* extensions declaration (i.e: JsExtension.js files).
|
||||
* Extension runtime files are in TypeScript (ts files) and not using Flow.
|
||||
*
|
||||
* If you do changes here, run `node import-GDJS-Runtime.js` (in newIDE/app/scripts),
|
||||
* and be sure that the types declared here are reflecting the types exposed by the editor.
|
||||
*
|
||||
* Note that Flow comments are used to avoid having to preprocess this file and the
|
||||
* JsExtension.js files through Babel. This allows to keep plain JS files, while allowing
|
||||
* Flow static type checking to be run on them when integrated in the editor.
|
||||
*/
|
||||
|
||||
/*::
|
||||
export type ObjectsRenderingService = {
|
||||
gd: libGDevelop,
|
||||
PIXI: any,
|
||||
THREE: any,
|
||||
THREE_ADDONS: {SkeletonUtils: any},
|
||||
RenderedInstance: any,
|
||||
Rendered3DInstance: any,
|
||||
registerInstanceRenderer: (objectType: string, renderer: any) => void,
|
||||
registerInstance3DRenderer: (objectType: string, renderer: any) => void,
|
||||
requireModule: (dirname: string, moduleName: string) => any,
|
||||
getThumbnail: (project: gdProject, objectConfiguration: gdObjectConfiguration) => string,
|
||||
rgbOrHexToHexNumber: (value: string) => number,
|
||||
registerClearCache: (clearCache: any => void) => void,
|
||||
};
|
||||
export type ObjectsEditorService = {
|
||||
registerEditorConfiguration: (objectType: string, editorConfiguration: any) => void,
|
||||
getDefaultObjectJsImplementationPropertiesEditor: ({| helpPagePath: string |}) => any,
|
||||
};
|
||||
*/
|
@@ -1,4 +1,5 @@
|
||||
// @flow
|
||||
//@ts-check
|
||||
/// <reference path="../JsExtensionTypes.d.ts" />
|
||||
/**
|
||||
* This is a declaration of an extension for GDevelop 5.
|
||||
*
|
||||
@@ -12,18 +13,9 @@
|
||||
* More information on https://github.com/4ian/GDevelop/blob/master/newIDE/README-extensions.md
|
||||
*/
|
||||
|
||||
/*::
|
||||
// Import types to allow Flow to do static type checking on this file.
|
||||
// Extensions declaration are typed using Flow (like the editor), but the files
|
||||
// for the game engine are checked with TypeScript annotations.
|
||||
import { type ObjectsRenderingService, type ObjectsEditorService } from '../JsExtensionTypes.flow.js'
|
||||
*/
|
||||
|
||||
/** @type {ExtensionModule} */
|
||||
module.exports = {
|
||||
createExtension: function (
|
||||
_ /*: (string) => string */,
|
||||
gd /*: libGDevelop */
|
||||
) {
|
||||
createExtension: function (_, gd) {
|
||||
const extension = new gd.PlatformExtension();
|
||||
extension
|
||||
.setExtensionInformation(
|
||||
@@ -96,7 +88,9 @@ module.exports = {
|
||||
.setIncludeFile('Extensions/Leaderboards/sha256.js')
|
||||
.addIncludeFile('Extensions/Leaderboards/leaderboardstools.js')
|
||||
.setFunctionName('gdjs.evtTools.leaderboards.saveConnectedPlayerScore')
|
||||
.setAsyncFunctionName('gdjs.evtTools.leaderboards.saveConnectedPlayerScore');
|
||||
.setAsyncFunctionName(
|
||||
'gdjs.evtTools.leaderboards.saveConnectedPlayerScore'
|
||||
);
|
||||
|
||||
extension
|
||||
.addCondition(
|
||||
@@ -299,10 +293,7 @@ module.exports = {
|
||||
|
||||
return extension;
|
||||
},
|
||||
runExtensionSanityTests: function (
|
||||
gd /*: libGDevelop */,
|
||||
extension /*: gdPlatformExtension*/
|
||||
) {
|
||||
runExtensionSanityTests: function (gd, extension) {
|
||||
return [];
|
||||
},
|
||||
};
|
||||
|
@@ -1,4 +1,5 @@
|
||||
// @flow
|
||||
//@ts-check
|
||||
/// <reference path="../JsExtensionTypes.d.ts" />
|
||||
/**
|
||||
* This is a declaration of an extension for GDevelop 5.
|
||||
*
|
||||
@@ -12,32 +13,23 @@
|
||||
* More information on https://github.com/4ian/GDevelop/blob/master/newIDE/README-extensions.md
|
||||
*/
|
||||
|
||||
/*::
|
||||
// Import types to allow Flow to do static type checking on this file.
|
||||
// Extensions declaration are typed using Flow (like the editor), but the files
|
||||
// for the game engine are checked with TypeScript annotations.
|
||||
import { type ObjectsRenderingService, type ObjectsEditorService } from '../JsExtensionTypes.flow.js'
|
||||
*/
|
||||
|
||||
/** @type {ExtensionModule} */
|
||||
module.exports = {
|
||||
createExtension: function (
|
||||
_ /*: (string) => string */,
|
||||
gd /*: libGDevelop */
|
||||
) {
|
||||
createExtension: function (_, gd) {
|
||||
const extension = new gd.PlatformExtension();
|
||||
extension.setExtensionInformation(
|
||||
'Lighting',
|
||||
_('Lights'),
|
||||
extension
|
||||
.setExtensionInformation(
|
||||
'Lighting',
|
||||
_('Lights'),
|
||||
|
||||
'This provides a light object, and a behavior to mark other objects as being obstacles for the lights. This is a great way to create a special atmosphere to your game, along with effects, make it more realistic or to create gameplays based on lights.',
|
||||
'Harsimran Virk',
|
||||
'MIT'
|
||||
)
|
||||
.setCategory('Visual effect')
|
||||
.setTags("light");
|
||||
'This provides a light object, and a behavior to mark other objects as being obstacles for the lights. This is a great way to create a special atmosphere to your game, along with effects, make it more realistic or to create gameplays based on lights.',
|
||||
'Harsimran Virk',
|
||||
'MIT'
|
||||
)
|
||||
.setCategory('Visual effect')
|
||||
.setTags('light');
|
||||
|
||||
const lightObstacleBehavior = new gd.BehaviorJsImplementation();
|
||||
// $FlowExpectedError - ignore Flow warning as we're creating a behavior
|
||||
lightObstacleBehavior.updateProperty = function (
|
||||
behaviorContent,
|
||||
propertyName,
|
||||
@@ -46,14 +38,12 @@ module.exports = {
|
||||
return false;
|
||||
};
|
||||
|
||||
// $FlowExpectedError - ignore Flow warning as we're creating a behavior
|
||||
lightObstacleBehavior.getProperties = function (behaviorContent) {
|
||||
const behaviorProperties = new gd.MapStringPropertyDescriptor();
|
||||
|
||||
return behaviorProperties;
|
||||
};
|
||||
|
||||
// $FlowExpectedError - ignore Flow warning as we're creating a behavior
|
||||
lightObstacleBehavior.initializeContent = function (behaviorContent) {};
|
||||
extension
|
||||
.addBehavior(
|
||||
@@ -66,6 +56,7 @@ module.exports = {
|
||||
'',
|
||||
'CppPlatform/Extensions/lightObstacleIcon32.png',
|
||||
'LightObstacleBehavior',
|
||||
//@ts-ignore The class hierarchy is incorrect leading to a type error, but this is valid.
|
||||
lightObstacleBehavior,
|
||||
new gd.BehaviorsSharedData()
|
||||
)
|
||||
@@ -77,7 +68,6 @@ module.exports = {
|
||||
|
||||
const lightObject = new gd.ObjectJsImplementation();
|
||||
|
||||
// $FlowExpectedError - ignore Flow warning as we're creating an object.
|
||||
lightObject.updateProperty = function (
|
||||
objectContent,
|
||||
propertyName,
|
||||
@@ -106,7 +96,6 @@ module.exports = {
|
||||
return false;
|
||||
};
|
||||
|
||||
// $FlowExpectedError - ignore Flow warning as we're creating an object.
|
||||
lightObject.getProperties = function (objectContent) {
|
||||
const objectProperties = new gd.MapStringPropertyDescriptor();
|
||||
|
||||
@@ -160,7 +149,6 @@ module.exports = {
|
||||
})
|
||||
);
|
||||
|
||||
// $FlowExpectedError - ignore Flow warning as we're creating an object.
|
||||
lightObject.updateInitialInstanceProperty = function (
|
||||
objectContent,
|
||||
instance,
|
||||
@@ -172,7 +160,6 @@ module.exports = {
|
||||
return false;
|
||||
};
|
||||
|
||||
// $FlowExpectedError - ignore Flow warning as we're creating an object.
|
||||
lightObject.getInitialInstanceProperties = function (
|
||||
content,
|
||||
instance,
|
||||
@@ -233,16 +220,11 @@ module.exports = {
|
||||
return extension;
|
||||
},
|
||||
|
||||
runExtensionSanityTests: function (
|
||||
gd /*: libGDevelop */,
|
||||
extension /*: gdPlatformExtension*/
|
||||
) {
|
||||
runExtensionSanityTests: function (gd, extension) {
|
||||
return [];
|
||||
},
|
||||
|
||||
registerEditorConfigurations: function (
|
||||
objectsEditorService /*: ObjectsEditorService */
|
||||
) {
|
||||
registerEditorConfigurations: function (objectsEditorService) {
|
||||
objectsEditorService.registerEditorConfiguration(
|
||||
'Lighting::LightObject',
|
||||
objectsEditorService.getDefaultObjectJsImplementationPropertiesEditor({
|
||||
@@ -255,9 +237,7 @@ module.exports = {
|
||||
*
|
||||
* ℹ️ Run `node import-GDJS-Runtime.js` (in newIDE/app/scripts) if you make any change.
|
||||
*/
|
||||
registerInstanceRenderers: function (
|
||||
objectsRenderingService /*: ObjectsRenderingService */
|
||||
) {
|
||||
registerInstanceRenderers: function (objectsRenderingService) {
|
||||
const RenderedInstance = objectsRenderingService.RenderedInstance;
|
||||
const PIXI = objectsRenderingService.PIXI;
|
||||
|
||||
@@ -283,32 +263,34 @@ module.exports = {
|
||||
);
|
||||
this._radius = parseFloat(
|
||||
this._associatedObjectConfiguration
|
||||
.getProperties(this.project)
|
||||
.getProperties()
|
||||
.get('radius')
|
||||
.getValue()
|
||||
);
|
||||
if (this._radius <= 0) this._radius = 1;
|
||||
const color = objectsRenderingService.rgbOrHexToHexNumber(
|
||||
this._associatedObjectConfiguration
|
||||
.getProperties(this.project)
|
||||
.getProperties()
|
||||
.get('color')
|
||||
.getValue()
|
||||
);
|
||||
|
||||
// The icon in the middle.
|
||||
const lightIconSprite = new PIXI.Sprite(PIXI.Texture.from('CppPlatform/Extensions/lightIcon32.png'));
|
||||
const lightIconSprite = new PIXI.Sprite(
|
||||
PIXI.Texture.from('CppPlatform/Extensions/lightIcon32.png')
|
||||
);
|
||||
lightIconSprite.anchor.x = 0.5;
|
||||
lightIconSprite.anchor.y = 0.5;
|
||||
|
||||
// The circle to show the radius of the light.
|
||||
const radiusBorderWidth = 2;
|
||||
const radiusGraphics = new PIXI.Graphics();
|
||||
radiusGraphics.lineStyle(
|
||||
radiusBorderWidth,
|
||||
color,
|
||||
0.8
|
||||
radiusGraphics.lineStyle(radiusBorderWidth, color, 0.8);
|
||||
radiusGraphics.drawCircle(
|
||||
0,
|
||||
0,
|
||||
Math.max(1, this._radius - radiusBorderWidth)
|
||||
);
|
||||
radiusGraphics.drawCircle(0, 0, Math.max(1, this._radius - radiusBorderWidth));
|
||||
|
||||
this._pixiObject = new PIXI.Container();
|
||||
this._pixiObject.addChild(lightIconSprite);
|
||||
@@ -326,11 +308,7 @@ module.exports = {
|
||||
/**
|
||||
* Return the path to the thumbnail of the specified object.
|
||||
*/
|
||||
static getThumbnail(
|
||||
project,
|
||||
resourcesLoader,
|
||||
objectConfiguration
|
||||
) {
|
||||
static getThumbnail(project, resourcesLoader, objectConfiguration) {
|
||||
return 'CppPlatform/Extensions/lightIcon32.png';
|
||||
}
|
||||
|
||||
|
@@ -1,4 +1,5 @@
|
||||
// @flow
|
||||
//@ts-check
|
||||
/// <reference path="../JsExtensionTypes.d.ts" />
|
||||
/**
|
||||
* This is a declaration of an extension for GDevelop 5.
|
||||
*
|
||||
@@ -12,18 +13,9 @@
|
||||
* More information on https://github.com/4ian/GDevelop/blob/master/newIDE/README-extensions.md
|
||||
*/
|
||||
|
||||
/*::
|
||||
// Import types to allow Flow to do static type checking on this file.
|
||||
// Extensions declaration are typed using Flow (like the editor), but the files
|
||||
// for the game engine are checked with TypeScript annotations.
|
||||
import { type ObjectsRenderingService, type ObjectsEditorService } from '../JsExtensionTypes.flow.js'
|
||||
*/
|
||||
|
||||
/** @type {ExtensionModule} */
|
||||
module.exports = {
|
||||
createExtension: function (
|
||||
_ /*: (string) => string */,
|
||||
gd /*: libGDevelop */
|
||||
) {
|
||||
createExtension: function (_, gd) {
|
||||
const extension /*: gdPlatformExtension */ = new gd.PlatformExtension();
|
||||
extension
|
||||
.setExtensionInformation(
|
||||
@@ -474,10 +466,7 @@ module.exports = {
|
||||
|
||||
return extension;
|
||||
},
|
||||
runExtensionSanityTests: function (
|
||||
gd /*: libGDevelop */,
|
||||
extension /*: gdPlatformExtension*/
|
||||
) {
|
||||
runExtensionSanityTests: function (gd, extension) {
|
||||
return [];
|
||||
},
|
||||
};
|
||||
|
@@ -1,4 +1,5 @@
|
||||
// @flow
|
||||
//@ts-check
|
||||
/// <reference path="../JsExtensionTypes.d.ts" />
|
||||
/**
|
||||
* This is a declaration of an extension for GDevelop 5.
|
||||
*
|
||||
@@ -12,18 +13,9 @@
|
||||
* More information on https://github.com/4ian/GDevelop/blob/master/newIDE/README-extensions.md
|
||||
*/
|
||||
|
||||
/*::
|
||||
// Import types to allow Flow to do static type checking on this file.
|
||||
// Extensions declaration are typed using Flow (like the editor), but the files
|
||||
// for the game engine are checked with TypeScript annotations.
|
||||
import { type ObjectsRenderingService, type ObjectsEditorService } from '../JsExtensionTypes.flow.js'
|
||||
*/
|
||||
|
||||
/** @type {ExtensionModule} */
|
||||
module.exports = {
|
||||
createExtension: function (
|
||||
_ /*: (string) => string */,
|
||||
gd /*: libGDevelop */
|
||||
) {
|
||||
createExtension: function (_, gd) {
|
||||
const extension = new gd.PlatformExtension();
|
||||
extension
|
||||
.setExtensionInformation(
|
||||
@@ -35,13 +27,12 @@ module.exports = {
|
||||
)
|
||||
.setExtensionHelpPath('/behaviors/physics2')
|
||||
.setCategory('Movement')
|
||||
.setTags("physics, gravity, obstacle, collision");
|
||||
.setTags('physics, gravity, obstacle, collision');
|
||||
extension
|
||||
.addInstructionOrExpressionGroupMetadata(_('Physics Engine 2.0'))
|
||||
.setIcon('res/physics32.png');
|
||||
|
||||
var physics2Behavior = new gd.BehaviorJsImplementation();
|
||||
// $FlowExpectedError - ignore Flow warning as we're creating a behavior
|
||||
physics2Behavior.updateProperty = function (
|
||||
behaviorContent,
|
||||
propertyName,
|
||||
@@ -51,104 +42,138 @@ module.exports = {
|
||||
behaviorContent.getChild('bodyType').setStringValue(newValue);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (propertyName === 'bullet') {
|
||||
behaviorContent.getChild('bullet').setBoolValue(newValue === '1');
|
||||
return true;
|
||||
}
|
||||
|
||||
if (propertyName === 'fixedRotation') {
|
||||
behaviorContent
|
||||
.getChild('fixedRotation')
|
||||
.setBoolValue(newValue === '1');
|
||||
return true;
|
||||
}
|
||||
|
||||
if (propertyName === 'canSleep') {
|
||||
behaviorContent.getChild('canSleep').setBoolValue(newValue === '1');
|
||||
return true;
|
||||
}
|
||||
|
||||
if (propertyName === 'shape') {
|
||||
behaviorContent.getChild('shape').setStringValue(newValue);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (propertyName === 'shapeDimensionA') {
|
||||
newValue = parseFloat(newValue);
|
||||
if (newValue !== newValue) return false;
|
||||
behaviorContent.getChild('shapeDimensionA').setDoubleValue(newValue);
|
||||
const newValueAsNumber = parseFloat(newValue);
|
||||
if (newValueAsNumber !== newValueAsNumber) return false;
|
||||
behaviorContent
|
||||
.getChild('shapeDimensionA')
|
||||
.setDoubleValue(newValueAsNumber);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (propertyName === 'shapeDimensionB') {
|
||||
newValue = parseFloat(newValue);
|
||||
if (newValue !== newValue) return false;
|
||||
behaviorContent.getChild('shapeDimensionB').setDoubleValue(newValue);
|
||||
const newValueAsNumber = parseFloat(newValue);
|
||||
if (newValueAsNumber !== newValueAsNumber) return false;
|
||||
behaviorContent
|
||||
.getChild('shapeDimensionB')
|
||||
.setDoubleValue(newValueAsNumber);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (propertyName === 'shapeOffsetX') {
|
||||
newValue = parseFloat(newValue);
|
||||
if (newValue !== newValue) return false;
|
||||
behaviorContent.getChild('shapeOffsetX').setDoubleValue(newValue);
|
||||
const newValueAsNumber = parseFloat(newValue);
|
||||
if (newValueAsNumber !== newValueAsNumber) return false;
|
||||
behaviorContent
|
||||
.getChild('shapeOffsetX')
|
||||
.setDoubleValue(newValueAsNumber);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (propertyName === 'shapeOffsetY') {
|
||||
newValue = parseFloat(newValue);
|
||||
if (newValue !== newValue) return false;
|
||||
behaviorContent.getChild('shapeOffsetY').setDoubleValue(newValue);
|
||||
const newValueAsNumber = parseFloat(newValue);
|
||||
if (newValueAsNumber !== newValueAsNumber) return false;
|
||||
behaviorContent
|
||||
.getChild('shapeOffsetY')
|
||||
.setDoubleValue(newValueAsNumber);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (propertyName === 'polygonOrigin') {
|
||||
behaviorContent.addChild('polygonOrigin').setStringValue(newValue);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (propertyName === 'vertices') {
|
||||
behaviorContent.addChild('vertices');
|
||||
// $FlowFixMe
|
||||
behaviorContent.setChild('vertices', gd.Serializer.fromJSON(newValue));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (propertyName === 'density') {
|
||||
behaviorContent
|
||||
.getChild('density')
|
||||
.setDoubleValue(parseFloat(newValue));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (propertyName === 'friction') {
|
||||
newValue = parseFloat(newValue);
|
||||
if (newValue !== newValue) return false;
|
||||
behaviorContent.getChild('friction').setDoubleValue(newValue);
|
||||
const newValueAsNumber = parseFloat(newValue);
|
||||
if (newValueAsNumber !== newValueAsNumber) return false;
|
||||
behaviorContent.getChild('friction').setDoubleValue(newValueAsNumber);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (propertyName === 'restitution') {
|
||||
newValue = parseFloat(newValue);
|
||||
if (newValue !== newValue) return false;
|
||||
behaviorContent.getChild('restitution').setDoubleValue(newValue);
|
||||
const newValueAsNumber = parseFloat(newValue);
|
||||
if (newValueAsNumber !== newValueAsNumber) return false;
|
||||
behaviorContent
|
||||
.getChild('restitution')
|
||||
.setDoubleValue(newValueAsNumber);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (propertyName === 'linearDamping') {
|
||||
newValue = parseFloat(newValue);
|
||||
if (newValue !== newValue) return false;
|
||||
behaviorContent.getChild('linearDamping').setDoubleValue(newValue);
|
||||
const newValueAsNumber = parseFloat(newValue);
|
||||
if (newValueAsNumber !== newValueAsNumber) return false;
|
||||
behaviorContent
|
||||
.getChild('linearDamping')
|
||||
.setDoubleValue(newValueAsNumber);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (propertyName === 'angularDamping') {
|
||||
newValue = parseFloat(newValue);
|
||||
if (newValue !== newValue) return false;
|
||||
behaviorContent.getChild('angularDamping').setDoubleValue(newValue);
|
||||
const newValueAsNumber = parseFloat(newValue);
|
||||
if (newValueAsNumber !== newValueAsNumber) return false;
|
||||
behaviorContent
|
||||
.getChild('angularDamping')
|
||||
.setDoubleValue(newValueAsNumber);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (propertyName === 'gravityScale') {
|
||||
newValue = parseFloat(newValue);
|
||||
if (newValue !== newValue) return false;
|
||||
behaviorContent.getChild('gravityScale').setDoubleValue(newValue);
|
||||
const newValueAsNumber = parseFloat(newValue);
|
||||
if (newValueAsNumber !== newValueAsNumber) return false;
|
||||
behaviorContent
|
||||
.getChild('gravityScale')
|
||||
.setDoubleValue(newValueAsNumber);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (propertyName === 'layers') {
|
||||
behaviorContent.getChild('layers').setIntValue(parseInt(newValue, 10));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (propertyName === 'masks') {
|
||||
behaviorContent.getChild('masks').setIntValue(parseInt(newValue, 10));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
// $FlowExpectedError - ignore Flow warning as we're creating a behavior
|
||||
physics2Behavior.getProperties = function (behaviorContent) {
|
||||
var behaviorProperties = new gd.MapStringPropertyDescriptor();
|
||||
|
||||
@@ -312,7 +337,6 @@ module.exports = {
|
||||
return behaviorProperties;
|
||||
};
|
||||
|
||||
// $FlowExpectedError - ignore Flow warning as we're creating a behavior
|
||||
physics2Behavior.initializeContent = function (behaviorContent) {
|
||||
behaviorContent.addChild('bodyType').setStringValue('Dynamic');
|
||||
behaviorContent.addChild('bullet').setBoolValue(false);
|
||||
@@ -336,40 +360,41 @@ module.exports = {
|
||||
};
|
||||
|
||||
var sharedData = new gd.BehaviorSharedDataJsImplementation();
|
||||
// $FlowExpectedError - ignore Flow warning as we're creating a behavior
|
||||
sharedData.updateProperty = function (
|
||||
sharedContent,
|
||||
propertyName,
|
||||
newValue
|
||||
) {
|
||||
if (propertyName === 'gravityX') {
|
||||
newValue = parseFloat(newValue);
|
||||
if (newValue !== newValue) return false;
|
||||
sharedContent.getChild('gravityX').setDoubleValue(newValue);
|
||||
const newValueAsNumber = parseFloat(newValue);
|
||||
if (newValueAsNumber !== newValueAsNumber) return false;
|
||||
sharedContent.getChild('gravityX').setDoubleValue(newValueAsNumber);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (propertyName === 'gravityY') {
|
||||
newValue = parseFloat(newValue);
|
||||
if (newValue !== newValue) return false;
|
||||
sharedContent.getChild('gravityY').setDoubleValue(newValue);
|
||||
const newValueAsNumber = parseFloat(newValue);
|
||||
if (newValueAsNumber !== newValueAsNumber) return false;
|
||||
sharedContent.getChild('gravityY').setDoubleValue(newValueAsNumber);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (propertyName === 'scaleX') {
|
||||
newValue = parseInt(newValue, 10);
|
||||
if (newValue !== newValue) return false;
|
||||
sharedContent.getChild('scaleX').setDoubleValue(newValue);
|
||||
const newValueAsNumber = parseInt(newValue, 10);
|
||||
if (newValueAsNumber !== newValueAsNumber) return false;
|
||||
sharedContent.getChild('scaleX').setDoubleValue(newValueAsNumber);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (propertyName === 'scaleY') {
|
||||
newValue = parseInt(newValue, 10);
|
||||
if (newValue !== newValue) return false;
|
||||
sharedContent.getChild('scaleY').setDoubleValue(newValue);
|
||||
const newValueAsNumber = parseInt(newValue, 10);
|
||||
if (newValueAsNumber !== newValueAsNumber) return false;
|
||||
sharedContent.getChild('scaleY').setDoubleValue(newValueAsNumber);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
// $FlowExpectedError - ignore Flow warning as we're creating a behavior
|
||||
sharedData.getProperties = function (sharedContent) {
|
||||
var sharedProperties = new gd.MapStringPropertyDescriptor();
|
||||
|
||||
@@ -402,7 +427,6 @@ module.exports = {
|
||||
|
||||
return sharedProperties;
|
||||
};
|
||||
// $FlowExpectedError - ignore Flow warning as we're creating a behavior
|
||||
sharedData.initializeContent = function (behaviorContent) {
|
||||
behaviorContent.addChild('gravityX').setDoubleValue(0);
|
||||
behaviorContent.addChild('gravityY').setDoubleValue(9.8);
|
||||
@@ -422,6 +446,7 @@ module.exports = {
|
||||
'',
|
||||
'res/physics32.png',
|
||||
'Physics2Behavior',
|
||||
//@ts-ignore The class hierarchy is incorrect leading to a type error, but this is valid.
|
||||
physics2Behavior,
|
||||
sharedData
|
||||
)
|
||||
@@ -775,10 +800,10 @@ module.exports = {
|
||||
.setDefaultValue('true')
|
||||
.getCodeExtraInformation()
|
||||
.setFunctionName('setSleepingAllowed');
|
||||
|
||||
|
||||
// Deprecated action (fixed typo):
|
||||
aut
|
||||
.addDuplicatedAction("SetSleepingaAllowed", "SetSleepingAllowed")
|
||||
.addDuplicatedAction('SetSleepingaAllowed', 'SetSleepingAllowed')
|
||||
.setHidden();
|
||||
|
||||
aut
|
||||
@@ -1476,10 +1501,16 @@ module.exports = {
|
||||
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
|
||||
.addParameter('expression', _('X component (N)'))
|
||||
.addParameter('expression', _('Y component (N)'))
|
||||
.setParameterLongDescription(_('A force is like an acceleration but depends on the mass.'))
|
||||
.setParameterLongDescription(
|
||||
_('A force is like an acceleration but depends on the mass.')
|
||||
)
|
||||
.addParameter('expression', _('Application point on X axis'))
|
||||
.addParameter('expression', _('Application point on Y axis'))
|
||||
.setParameterLongDescription(_('Use `MassCenterX` and `MassCenterY` expressions to avoid any rotation.'))
|
||||
.setParameterLongDescription(
|
||||
_(
|
||||
'Use `MassCenterX` and `MassCenterY` expressions to avoid any rotation.'
|
||||
)
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setFunctionName('applyForce');
|
||||
|
||||
@@ -1499,10 +1530,16 @@ module.exports = {
|
||||
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
|
||||
.addParameter('expression', _('Angle'))
|
||||
.addParameter('expression', _('Length (N)'))
|
||||
.setParameterLongDescription(_('A force is like an acceleration but depends on the mass.'))
|
||||
.setParameterLongDescription(
|
||||
_('A force is like an acceleration but depends on the mass.')
|
||||
)
|
||||
.addParameter('expression', _('Application point on X axis'))
|
||||
.addParameter('expression', _('Application point on Y axis'))
|
||||
.setParameterLongDescription(_('Use `MassCenterX` and `MassCenterY` expressions to avoid any rotation.'))
|
||||
.setParameterLongDescription(
|
||||
_(
|
||||
'Use `MassCenterX` and `MassCenterY` expressions to avoid any rotation.'
|
||||
)
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setFunctionName('applyPolarForce');
|
||||
|
||||
@@ -1523,12 +1560,18 @@ module.exports = {
|
||||
.addParameter('object', _('Object'), '', false)
|
||||
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
|
||||
.addParameter('expression', _('Length (N)'))
|
||||
.setParameterLongDescription(_('A force is like an acceleration but depends on the mass.'))
|
||||
.setParameterLongDescription(
|
||||
_('A force is like an acceleration but depends on the mass.')
|
||||
)
|
||||
.addParameter('expression', _('X position'))
|
||||
.addParameter('expression', _('Y position'))
|
||||
.addParameter('expression', _('Application point on X axis'))
|
||||
.addParameter('expression', _('Application point on Y axis'))
|
||||
.setParameterLongDescription(_('Use `MassCenterX` and `MassCenterY` expressions to avoid any rotation.'))
|
||||
.setParameterLongDescription(
|
||||
_(
|
||||
'Use `MassCenterX` and `MassCenterY` expressions to avoid any rotation.'
|
||||
)
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setFunctionName('applyForceTowardPosition');
|
||||
|
||||
@@ -1546,18 +1589,18 @@ module.exports = {
|
||||
)
|
||||
.addParameter('object', _('Object'), '', false)
|
||||
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
|
||||
.addParameter(
|
||||
'expression',
|
||||
_('X component (N·s or kg·m·s⁻¹)')
|
||||
.addParameter('expression', _('X component (N·s or kg·m·s⁻¹)'))
|
||||
.addParameter('expression', _('Y component (N·s or kg·m·s⁻¹)'))
|
||||
.setParameterLongDescription(
|
||||
_('An impulse is like a speed addition but depends on the mass.')
|
||||
)
|
||||
.addParameter(
|
||||
'expression',
|
||||
_('Y component (N·s or kg·m·s⁻¹)')
|
||||
)
|
||||
.setParameterLongDescription(_('An impulse is like a speed addition but depends on the mass.'))
|
||||
.addParameter('expression', _('Application point on X axis'))
|
||||
.addParameter('expression', _('Application point on Y axis'))
|
||||
.setParameterLongDescription(_('Use `MassCenterX` and `MassCenterY` expressions to avoid any rotation.'))
|
||||
.setParameterLongDescription(
|
||||
_(
|
||||
'Use `MassCenterX` and `MassCenterY` expressions to avoid any rotation.'
|
||||
)
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setFunctionName('applyImpulse');
|
||||
|
||||
@@ -1578,14 +1621,17 @@ module.exports = {
|
||||
.addParameter('object', _('Object'), '', false)
|
||||
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
|
||||
.addParameter('expression', _('Angle'))
|
||||
.addParameter(
|
||||
'expression',
|
||||
_('Length (N·s or kg·m·s⁻¹)')
|
||||
.addParameter('expression', _('Length (N·s or kg·m·s⁻¹)'))
|
||||
.setParameterLongDescription(
|
||||
_('An impulse is like a speed addition but depends on the mass.')
|
||||
)
|
||||
.setParameterLongDescription(_('An impulse is like a speed addition but depends on the mass.'))
|
||||
.addParameter('expression', _('Application point on X axis'))
|
||||
.addParameter('expression', _('Application point on Y axis'))
|
||||
.setParameterLongDescription(_('Use `MassCenterX` and `MassCenterY` expressions to avoid any rotation.'))
|
||||
.setParameterLongDescription(
|
||||
_(
|
||||
'Use `MassCenterX` and `MassCenterY` expressions to avoid any rotation.'
|
||||
)
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setFunctionName('applyPolarImpulse');
|
||||
|
||||
@@ -1605,16 +1651,19 @@ module.exports = {
|
||||
)
|
||||
.addParameter('object', _('Object'), '', false)
|
||||
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
|
||||
.addParameter(
|
||||
'expression',
|
||||
_('Length (N·s or kg·m·s⁻¹)')
|
||||
.addParameter('expression', _('Length (N·s or kg·m·s⁻¹)'))
|
||||
.setParameterLongDescription(
|
||||
_('An impulse is like a speed addition but depends on the mass.')
|
||||
)
|
||||
.setParameterLongDescription(_('An impulse is like a speed addition but depends on the mass.'))
|
||||
.addParameter('expression', _('X position'))
|
||||
.addParameter('expression', _('Y position'))
|
||||
.addParameter('expression', _('Application point on X axis'))
|
||||
.addParameter('expression', _('Application point on Y axis'))
|
||||
.setParameterLongDescription(_('Use `MassCenterX` and `MassCenterY` expressions to avoid any rotation.'))
|
||||
.setParameterLongDescription(
|
||||
_(
|
||||
'Use `MassCenterX` and `MassCenterY` expressions to avoid any rotation.'
|
||||
)
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setFunctionName('applyImpulseTowardPosition');
|
||||
|
||||
@@ -1633,7 +1682,9 @@ module.exports = {
|
||||
.addParameter('object', _('Object'), '', false)
|
||||
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
|
||||
.addParameter('expression', _('Torque (N·m)'))
|
||||
.setParameterLongDescription(_('A torque is like a rotation acceleration but depends on the mass.'))
|
||||
.setParameterLongDescription(
|
||||
_('A torque is like a rotation acceleration but depends on the mass.')
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setFunctionName('applyTorque');
|
||||
|
||||
@@ -1652,7 +1703,11 @@ module.exports = {
|
||||
.addParameter('object', _('Object'), '', false)
|
||||
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
|
||||
.addParameter('expression', _('Angular impulse (N·m·s'))
|
||||
.setParameterLongDescription(_('An impulse is like a rotation speed addition but depends on the mass.'))
|
||||
.setParameterLongDescription(
|
||||
_(
|
||||
'An impulse is like a rotation speed addition but depends on the mass.'
|
||||
)
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setFunctionName('applyAngularImpulse');
|
||||
|
||||
@@ -4061,10 +4116,7 @@ module.exports = {
|
||||
return extension;
|
||||
},
|
||||
|
||||
runExtensionSanityTests: function (
|
||||
gd /*: libGDevelop */,
|
||||
extension /*: gdPlatformExtension*/
|
||||
) {
|
||||
runExtensionSanityTests: function (gd, extension) {
|
||||
const dummyBehavior = extension
|
||||
.getBehaviorMetadata('Physics2::Physics2Behavior')
|
||||
.get();
|
||||
|
@@ -1,4 +1,5 @@
|
||||
// @flow
|
||||
//@ts-check
|
||||
/// <reference path="../JsExtensionTypes.d.ts" />
|
||||
/**
|
||||
* This is a declaration of an extension for GDevelop 5.
|
||||
*
|
||||
@@ -12,18 +13,9 @@
|
||||
* More information on https://github.com/4ian/GDevelop/blob/master/newIDE/README-extensions.md
|
||||
*/
|
||||
|
||||
/*::
|
||||
// Import types to allow Flow to do static type checking on this file.
|
||||
// Extensions declaration are typed using Flow (like the editor), but the files
|
||||
// for the game engine are checked with TypeScript annotations.
|
||||
import { type ObjectsRenderingService, type ObjectsEditorService } from '../JsExtensionTypes.flow.js'
|
||||
*/
|
||||
|
||||
/** @type {ExtensionModule} */
|
||||
module.exports = {
|
||||
createExtension: function (
|
||||
_ /*: (string) => string */,
|
||||
gd /*: libGDevelop */
|
||||
) {
|
||||
createExtension: function (_, gd) {
|
||||
const extension = new gd.PlatformExtension();
|
||||
extension
|
||||
.setExtensionInformation(
|
||||
@@ -72,9 +64,7 @@ module.exports = {
|
||||
.addAction(
|
||||
'HideAuthenticationBanner',
|
||||
_('Hide authentication banner'),
|
||||
_(
|
||||
'Hide the authentication banner from the top of the game screen.'
|
||||
),
|
||||
_('Hide the authentication banner from the top of the game screen.'),
|
||||
_('Hide the authentication banner'),
|
||||
'',
|
||||
'JsPlatform/Extensions/authentication.svg',
|
||||
@@ -226,10 +216,7 @@ module.exports = {
|
||||
|
||||
return extension;
|
||||
},
|
||||
runExtensionSanityTests: function (
|
||||
gd /*: libGDevelop */,
|
||||
extension /*: gdPlatformExtension*/
|
||||
) {
|
||||
runExtensionSanityTests: function (gd, extension) {
|
||||
return [];
|
||||
},
|
||||
};
|
||||
|
@@ -124,6 +124,25 @@ void DeclarePrimitiveDrawingExtension(gd::PlatformExtension& extension) {
|
||||
.AddParameter("expression", _("The height of the ellipse"))
|
||||
.SetFunctionName("DrawEllipse");
|
||||
|
||||
obj.AddAction("FilletRectangle",
|
||||
_("Fillet Rectangle"),
|
||||
_("Draw a fillet rectangle on screen"),
|
||||
_("Draw from _PARAM1_;_PARAM2_ to _PARAM3_;_PARAM4_ a fillet "
|
||||
"rectangle (fillet: _PARAM5_)"
|
||||
"with _PARAM0_"),
|
||||
_("Drawing"),
|
||||
"res/actions/filletRectangle24.png",
|
||||
"res/actions/filletRectangle.png")
|
||||
|
||||
.AddParameter("object", _("Shape Painter object"), "Drawer")
|
||||
.AddParameter("expression", _("Left X position"))
|
||||
.AddParameter("expression", _("Top Y position"))
|
||||
.AddParameter("expression", _("Right X position"))
|
||||
.AddParameter("expression", _("Bottom Y position"))
|
||||
.AddParameter("expression", _("Fillet (in pixels)"))
|
||||
.SetFunctionName("DrawFilletRectangle");
|
||||
|
||||
|
||||
obj.AddAction("RoundedRectangle",
|
||||
_("Rounded rectangle"),
|
||||
_("Draw a rounded rectangle on screen"),
|
||||
|
@@ -47,6 +47,11 @@ class PrimitiveDrawingJsExtension : public gd::PlatformExtension {
|
||||
GetAllActionsForObject(
|
||||
"PrimitiveDrawing::Drawer")["PrimitiveDrawing::Ellipse"]
|
||||
.SetFunctionName("drawEllipse");
|
||||
|
||||
GetAllActionsForObject(
|
||||
"PrimitiveDrawing::Drawer")["PrimitiveDrawing::FilletRectangle"]
|
||||
.SetFunctionName("drawFilletRectangle");
|
||||
|
||||
GetAllActionsForObject(
|
||||
"PrimitiveDrawing::Drawer")["PrimitiveDrawing::RoundedRectangle"]
|
||||
.SetFunctionName("drawRoundedRectangle");
|
||||
|
@@ -136,6 +136,25 @@ namespace gdjs {
|
||||
this.invalidateBounds();
|
||||
}
|
||||
|
||||
drawFilletRectangle(
|
||||
x1: float,
|
||||
y1: float,
|
||||
x2: float,
|
||||
y2: float,
|
||||
fillet: float
|
||||
) {
|
||||
this.updateOutline();
|
||||
this._graphics.beginFill(
|
||||
this._object._fillColor,
|
||||
this._object._fillOpacity / 255
|
||||
);
|
||||
//@ts-ignore from @pixi/graphics-extras
|
||||
this._graphics.drawFilletRect(x1, y1, x2 - x1, y2 - y1, fillet);
|
||||
this._graphics.closePath();
|
||||
this._graphics.endFill();
|
||||
this.invalidateBounds();
|
||||
}
|
||||
|
||||
drawChamferRectangle(
|
||||
x1: float,
|
||||
y1: float,
|
||||
|
@@ -210,6 +210,22 @@ namespace gdjs {
|
||||
this._renderer.drawEllipse(centerX, centerY, width, height);
|
||||
}
|
||||
|
||||
drawFilletRectangle(
|
||||
startX1: float,
|
||||
startY1: float,
|
||||
endX2: float,
|
||||
endY2: float,
|
||||
fillet: float
|
||||
) {
|
||||
this._renderer.drawFilletRectangle(
|
||||
startX1,
|
||||
startY1,
|
||||
endX2,
|
||||
endY2,
|
||||
fillet
|
||||
);
|
||||
}
|
||||
|
||||
drawRoundedRectangle(
|
||||
startX1: float,
|
||||
startY1: float,
|
||||
|
@@ -1,4 +1,5 @@
|
||||
// @flow
|
||||
//@ts-check
|
||||
/// <reference path="../JsExtensionTypes.d.ts" />
|
||||
/**
|
||||
* This is a declaration of an extension for GDevelop 5.
|
||||
*
|
||||
@@ -12,18 +13,9 @@
|
||||
* More information on https://github.com/4ian/GDevelop/blob/master/newIDE/README-extensions.md
|
||||
*/
|
||||
|
||||
/*::
|
||||
// Import types to allow Flow to do static type checking on this file.
|
||||
// Extensions declaration are typed using Flow (like the editor), but the files
|
||||
// for the game engine are checked with TypeScript annotations.
|
||||
import { type ObjectsRenderingService, type ObjectsEditorService } from '../JsExtensionTypes.flow.js'
|
||||
*/
|
||||
|
||||
/** @type {ExtensionModule} */
|
||||
module.exports = {
|
||||
createExtension: function (
|
||||
_ /*: (string) => string */,
|
||||
gd /*: libGDevelop */
|
||||
) {
|
||||
createExtension: function (_, gd) {
|
||||
const extension = new gd.PlatformExtension();
|
||||
extension
|
||||
.setExtensionInformation(
|
||||
@@ -59,10 +51,7 @@ module.exports = {
|
||||
|
||||
return extension;
|
||||
},
|
||||
runExtensionSanityTests: function (
|
||||
gd /*: libGDevelop */,
|
||||
extension /*: gdPlatformExtension*/
|
||||
) {
|
||||
runExtensionSanityTests: function (gd, extension) {
|
||||
return [];
|
||||
},
|
||||
};
|
||||
|
@@ -1,4 +1,5 @@
|
||||
// @flow
|
||||
//@ts-check
|
||||
/// <reference path="../JsExtensionTypes.d.ts" />
|
||||
/**
|
||||
* This is a declaration of an extension for GDevelop 5.
|
||||
*
|
||||
@@ -12,18 +13,9 @@
|
||||
* More information on https://github.com/4ian/GDevelop/blob/master/newIDE/README-extensions.md
|
||||
*/
|
||||
|
||||
/*::
|
||||
// Import types to allow Flow to do static type checking on this file.
|
||||
// Extensions declaration are typed using Flow (like the editor), but the files
|
||||
// for the game engine are checked with TypeScript annotations.
|
||||
import { type ObjectsRenderingService, type ObjectsEditorService } from '../JsExtensionTypes.flow.js'
|
||||
*/
|
||||
|
||||
/** @type {ExtensionModule} */
|
||||
module.exports = {
|
||||
createExtension: function (
|
||||
_ /*: (string) => string */,
|
||||
gd /*: libGDevelop */
|
||||
) {
|
||||
createExtension: function (_, gd) {
|
||||
const extension = new gd.PlatformExtension();
|
||||
extension
|
||||
.setExtensionInformation(
|
||||
@@ -83,10 +75,7 @@ module.exports = {
|
||||
|
||||
return extension;
|
||||
},
|
||||
runExtensionSanityTests: function (
|
||||
gd /*: libGDevelop */,
|
||||
extension /*: gdPlatformExtension*/
|
||||
) {
|
||||
runExtensionSanityTests: function (gd, extension) {
|
||||
return [];
|
||||
},
|
||||
};
|
||||
|
@@ -1,4 +1,5 @@
|
||||
// @flow
|
||||
// @ts-check
|
||||
/// <reference path="../JsExtensionTypes.d.ts" />
|
||||
/**
|
||||
* This is a declaration of an extension for GDevelop 5.
|
||||
*
|
||||
@@ -12,18 +13,9 @@
|
||||
* More information on https://github.com/4ian/GDevelop/blob/master/newIDE/README-extensions.md
|
||||
*/
|
||||
|
||||
/*::
|
||||
// Import types to allow Flow to do static type checking on this file.
|
||||
// Extensions declaration are typed using Flow (like the editor), but the files
|
||||
// for the game engine are checked with TypeScript annotations.
|
||||
import { type ObjectsRenderingService, type ObjectsEditorService } from '../JsExtensionTypes.flow.js'
|
||||
*/
|
||||
|
||||
/** @type {ExtensionModule} */
|
||||
module.exports = {
|
||||
createExtension: function (
|
||||
_ /*: (string) => string */,
|
||||
gd /*: libGDevelop */
|
||||
) {
|
||||
createExtension: function (_, gd) {
|
||||
const extension = new gd.PlatformExtension();
|
||||
|
||||
extension
|
||||
@@ -94,10 +86,7 @@ module.exports = {
|
||||
* But it is recommended to create tests for the behaviors/objects properties you created
|
||||
* to avoid mistakes.
|
||||
*/
|
||||
runExtensionSanityTests: function (
|
||||
gd /*: libGDevelop */,
|
||||
extension /*: gdPlatformExtension*/
|
||||
) {
|
||||
runExtensionSanityTests: function (gd, extension) {
|
||||
return [];
|
||||
},
|
||||
/**
|
||||
@@ -105,17 +94,13 @@ module.exports = {
|
||||
*
|
||||
* ℹ️ Run `node import-GDJS-Runtime.js` (in newIDE/app/scripts) if you make any change.
|
||||
*/
|
||||
registerEditorConfigurations: function (
|
||||
objectsEditorService /*: ObjectsEditorService */
|
||||
) {},
|
||||
registerEditorConfigurations: function (objectsEditorService) {},
|
||||
/**
|
||||
* Register renderers for instance of objects on the scene editor.
|
||||
*
|
||||
* ℹ️ Run `node import-GDJS-Runtime.js` (in newIDE/app/scripts) if you make any change.
|
||||
*/
|
||||
registerInstanceRenderers: function (
|
||||
objectsRenderingService /*: ObjectsRenderingService */
|
||||
) {
|
||||
registerInstanceRenderers: function (objectsRenderingService) {
|
||||
const { PIXI, RenderedInstance, gd } = objectsRenderingService;
|
||||
|
||||
class RenderedSpineInstance extends RenderedInstance {
|
||||
@@ -228,7 +213,6 @@ module.exports = {
|
||||
const animation = configuration.getAnimation(index);
|
||||
const source = animation.getSource();
|
||||
const shouldLoop = animation.shouldLoop();
|
||||
const scale = this.getScale();
|
||||
|
||||
// reset scale to track new animation range
|
||||
// if custom size is set it will be reinitialized in update method
|
||||
|
@@ -1,4 +1,5 @@
|
||||
// @flow
|
||||
//@ts-check
|
||||
/// <reference path="../JsExtensionTypes.d.ts" />
|
||||
/**
|
||||
* This is a declaration of an extension for GDevelop 5.
|
||||
*
|
||||
@@ -12,18 +13,9 @@
|
||||
* More information on https://github.com/4ian/GDevelop/blob/master/newIDE/README-extensions.md
|
||||
*/
|
||||
|
||||
/*::
|
||||
// Import types to allow Flow to do static type checking on this file.
|
||||
// Extensions declaration are typed using Flow (like the editor), but the files
|
||||
// for the game engine are checked with TypeScript annotations.
|
||||
import { type ObjectsRenderingService, type ObjectsEditorService } from '../JsExtensionTypes.flow.js'
|
||||
*/
|
||||
|
||||
/** @type {ExtensionModule} */
|
||||
module.exports = {
|
||||
createExtension: function (
|
||||
_ /*: (string) => string */,
|
||||
gd /*: libGDevelop */
|
||||
) {
|
||||
createExtension: function (_, gd) {
|
||||
const extension = new gd.PlatformExtension();
|
||||
extension
|
||||
.setExtensionInformation(
|
||||
@@ -1243,10 +1235,7 @@ module.exports = {
|
||||
|
||||
return extension;
|
||||
},
|
||||
runExtensionSanityTests: function (
|
||||
gd /*: libGDevelop */,
|
||||
extension /*: gdPlatformExtension*/
|
||||
) {
|
||||
runExtensionSanityTests: function (gd, extension) {
|
||||
return [];
|
||||
},
|
||||
};
|
||||
|
@@ -1,4 +1,5 @@
|
||||
// @flow
|
||||
//@ts-check
|
||||
/// <reference path="../JsExtensionTypes.d.ts" />
|
||||
/**
|
||||
* This is a declaration of an extension for GDevelop 5.
|
||||
*
|
||||
@@ -12,18 +13,9 @@
|
||||
* More information on https://github.com/4ian/GDevelop/blob/master/newIDE/README-extensions.md
|
||||
*/
|
||||
|
||||
/*::
|
||||
// Import types to allow Flow to do static type checking on this file.
|
||||
// Extensions declaration are typed using Flow (like the editor), but the files
|
||||
// for the game engine are checked with TypeScript annotations.
|
||||
import { type ObjectsRenderingService, type ObjectsEditorService } from '../JsExtensionTypes.flow.js'
|
||||
*/
|
||||
|
||||
/** @type {ExtensionModule} */
|
||||
module.exports = {
|
||||
createExtension: function (
|
||||
_ /*: (string) => string */,
|
||||
gd /*: libGDevelop */
|
||||
) {
|
||||
createExtension: function (_, gd) {
|
||||
const extension = new gd.PlatformExtension();
|
||||
extension
|
||||
.setExtensionInformation(
|
||||
@@ -39,7 +31,6 @@ module.exports = {
|
||||
.setIcon('JsPlatform/Extensions/text_input.svg');
|
||||
|
||||
const textInputObject = new gd.ObjectJsImplementation();
|
||||
// $FlowExpectedError - ignore Flow warning as we're creating an object
|
||||
textInputObject.updateProperty = function (
|
||||
objectContent,
|
||||
propertyName,
|
||||
@@ -94,7 +85,6 @@ module.exports = {
|
||||
|
||||
return false;
|
||||
};
|
||||
// $FlowExpectedError - ignore Flow warning as we're creating an object
|
||||
textInputObject.getProperties = function (objectContent) {
|
||||
const objectProperties = new gd.MapStringPropertyDescriptor();
|
||||
|
||||
@@ -232,7 +222,6 @@ module.exports = {
|
||||
})
|
||||
);
|
||||
|
||||
// $FlowExpectedError - ignore Flow warning as we're creating an object
|
||||
textInputObject.updateInitialInstanceProperty = function (
|
||||
objectContent,
|
||||
instance,
|
||||
@@ -251,7 +240,6 @@ module.exports = {
|
||||
|
||||
return false;
|
||||
};
|
||||
// $FlowExpectedError - ignore Flow warning as we're creating an object
|
||||
textInputObject.getInitialInstanceProperties = function (
|
||||
content,
|
||||
instance,
|
||||
@@ -288,7 +276,7 @@ module.exports = {
|
||||
.addIncludeFile(
|
||||
'Extensions/TextInput/textinputruntimeobject-pixi-renderer.js'
|
||||
)
|
||||
.addDefaultBehavior("TextContainerCapability::TextContainerBehavior")
|
||||
.addDefaultBehavior('TextContainerCapability::TextContainerBehavior')
|
||||
.addDefaultBehavior('ResizableCapability::ResizableBehavior')
|
||||
.addDefaultBehavior('OpacityCapability::OpacityBehavior');
|
||||
|
||||
@@ -599,7 +587,9 @@ module.exports = {
|
||||
.addScopedAction(
|
||||
'Focus',
|
||||
_('Focus'),
|
||||
_('Focus the input so that text can be entered (like if it was touched/clicked).'),
|
||||
_(
|
||||
'Focus the input so that text can be entered (like if it was touched/clicked).'
|
||||
),
|
||||
_('Focus _PARAM0_'),
|
||||
_(''),
|
||||
'res/conditions/surObjet24.png',
|
||||
@@ -621,10 +611,7 @@ module.exports = {
|
||||
* But it is recommended to create tests for the behaviors/objects properties you created
|
||||
* to avoid mistakes.
|
||||
*/
|
||||
runExtensionSanityTests: function (
|
||||
gd /*: libGDevelop */,
|
||||
extension /*: gdPlatformExtension*/
|
||||
) {
|
||||
runExtensionSanityTests: function (gd, extension) {
|
||||
return [];
|
||||
},
|
||||
/**
|
||||
@@ -632,9 +619,7 @@ module.exports = {
|
||||
*
|
||||
* ℹ️ Run `node import-GDJS-Runtime.js` (in newIDE/app/scripts) if you make any change.
|
||||
*/
|
||||
registerEditorConfigurations: function (
|
||||
objectsEditorService /*: ObjectsEditorService */
|
||||
) {
|
||||
registerEditorConfigurations: function (objectsEditorService) {
|
||||
objectsEditorService.registerEditorConfiguration(
|
||||
'TextInput::TextInputObject',
|
||||
objectsEditorService.getDefaultObjectJsImplementationPropertiesEditor({
|
||||
@@ -647,9 +632,7 @@ module.exports = {
|
||||
*
|
||||
* ℹ️ Run `node import-GDJS-Runtime.js` (in newIDE/app/scripts) if you make any change.
|
||||
*/
|
||||
registerInstanceRenderers: function (
|
||||
objectsRenderingService /*: ObjectsRenderingService */
|
||||
) {
|
||||
registerInstanceRenderers: function (objectsRenderingService) {
|
||||
const RenderedInstance = objectsRenderingService.RenderedInstance;
|
||||
const PIXI = objectsRenderingService.PIXI;
|
||||
|
||||
|
@@ -40,38 +40,6 @@ void DeclareTextObjectExtension(gd::PlatformExtension& extension) {
|
||||
.AddDefaultBehavior("ScalableCapability::ScalableBehavior")
|
||||
.AddDefaultBehavior("OpacityCapability::OpacityBehavior");
|
||||
|
||||
// Deprecated
|
||||
obj.AddAction("String",
|
||||
_("Modify the text"),
|
||||
_("Modify the text of a Text object."),
|
||||
_("the text"),
|
||||
"",
|
||||
"res/actions/text24_black.png",
|
||||
"res/actions/text_black.png")
|
||||
.SetHidden()
|
||||
.AddParameter("object", _("Object"), "Text")
|
||||
.UseStandardOperatorParameters(
|
||||
"string",
|
||||
gd::ParameterOptions::MakeNewOptions().SetDescription(_("Text")))
|
||||
.SetFunctionName("SetString")
|
||||
.SetGetter("GetString");
|
||||
|
||||
// Deprecated
|
||||
obj.AddCondition("String",
|
||||
_("Compare the text"),
|
||||
_("Compare the text of a Text object."),
|
||||
_("the text"),
|
||||
"",
|
||||
"res/conditions/text24_black.png",
|
||||
"res/conditions/text_black.png")
|
||||
.SetHidden()
|
||||
.AddParameter("object", _("Object"), "Text")
|
||||
.UseStandardRelationalOperatorParameters(
|
||||
"string",
|
||||
gd::ParameterOptions::MakeNewOptions().SetDescription(
|
||||
_("Text to compare to")))
|
||||
.SetFunctionName("GetString");
|
||||
|
||||
obj.AddAction("Font",
|
||||
_("Font"),
|
||||
_("Change the font of the text."),
|
||||
@@ -84,94 +52,6 @@ void DeclareTextObjectExtension(gd::PlatformExtension& extension) {
|
||||
.AddParameter("police", _("Font"))
|
||||
.SetFunctionName("ChangeFont");
|
||||
|
||||
// Deprecated
|
||||
obj.AddCondition("ScaleX",
|
||||
_("Scale on X axis"),
|
||||
_("Compare the scale of the text on the X axis"),
|
||||
_("the scale on the X axis"),
|
||||
"Scale",
|
||||
"res/conditions/scaleWidth24_black.png",
|
||||
"res/conditions/scaleWidth_black.png")
|
||||
|
||||
.AddParameter("object", _("Object"), "Text")
|
||||
.UseStandardRelationalOperatorParameters(
|
||||
"number",
|
||||
gd::ParameterOptions::MakeNewOptions().SetDescription(
|
||||
_("Scale to compare to (1 by default)")))
|
||||
.SetHidden()
|
||||
.SetFunctionName("GetScaleX");
|
||||
|
||||
// Deprecated
|
||||
obj.AddAction(
|
||||
"ScaleX",
|
||||
_("Scale on X axis"),
|
||||
_("Modify the scale of the text on the X axis (default scale is 1)"),
|
||||
_("the scale on the X axis"),
|
||||
_("Scale"),
|
||||
"res/actions/scaleWidth24_black.png",
|
||||
"res/actions/scaleWidth_black.png")
|
||||
|
||||
.AddParameter("object", _("Object"), "Text")
|
||||
.UseStandardOperatorParameters(
|
||||
"number",
|
||||
gd::ParameterOptions::MakeNewOptions().SetDescription(
|
||||
_("Scale (1 by default)")))
|
||||
.SetHidden()
|
||||
.SetFunctionName("SetScaleX");
|
||||
|
||||
// Deprecated
|
||||
obj.AddCondition("ScaleY",
|
||||
_("Scale on Y axis"),
|
||||
_("Compare the scale of the text on the Y axis"),
|
||||
_("the scale on the Y axis"),
|
||||
"Scale",
|
||||
"res/conditions/scaleHeight24_black.png",
|
||||
"res/conditions/scaleHeight_black.png")
|
||||
|
||||
.AddParameter("object", _("Object"), "Text")
|
||||
.UseStandardRelationalOperatorParameters(
|
||||
"number",
|
||||
gd::ParameterOptions::MakeNewOptions().SetDescription(
|
||||
_("Scale to compare to (1 by default)")))
|
||||
.SetHidden()
|
||||
.SetFunctionName("GetScaleY");
|
||||
|
||||
// Deprecated
|
||||
obj.AddAction(
|
||||
"ScaleY",
|
||||
_("Scale on Y axis"),
|
||||
_("Modify the scale of the text on the Y axis (default scale is 1)"),
|
||||
_("the scale on the Y axis"),
|
||||
_("Scale"),
|
||||
"res/actions/scaleHeight24_black.png",
|
||||
"res/actions/scaleHeight_black.png")
|
||||
|
||||
.AddParameter("object", _("Object"), "Text")
|
||||
.UseStandardOperatorParameters(
|
||||
"number",
|
||||
gd::ParameterOptions::MakeNewOptions().SetDescription(
|
||||
_("Scale (1 by default)")))
|
||||
.SetHidden()
|
||||
.SetFunctionName("SetScaleY");
|
||||
|
||||
// Deprecated
|
||||
obj.AddAction(
|
||||
"Scale",
|
||||
_("Scale"),
|
||||
_("Modify the scale of the specified object (default scale is 1)"),
|
||||
_("the scale"),
|
||||
_("Scale"),
|
||||
"res/actions/scale24_black.png",
|
||||
"res/actions/scale_black.png")
|
||||
|
||||
.AddParameter("object", _("Object"), "Text")
|
||||
.UseStandardOperatorParameters(
|
||||
"number",
|
||||
gd::ParameterOptions::MakeNewOptions().SetDescription(
|
||||
_("Scale (1 by default)")))
|
||||
.SetHidden()
|
||||
.SetFunctionName("SetScale");
|
||||
|
||||
obj.AddAction(
|
||||
"ChangeColor",
|
||||
_("Color"),
|
||||
@@ -355,43 +235,6 @@ void DeclareTextObjectExtension(gd::PlatformExtension& extension) {
|
||||
gd::ParameterOptions::MakeNewOptions().SetDescription(
|
||||
_("Blur radius")));
|
||||
|
||||
// Deprecated
|
||||
obj.AddAction("Opacity",
|
||||
_("Text opacity"),
|
||||
_("Change the opacity of a Text. 0 is fully transparent, 255 "
|
||||
"is opaque (default)."),
|
||||
_("the opacity"),
|
||||
"",
|
||||
"res/actions/opacity24.png",
|
||||
"res/actions/opacity.png")
|
||||
|
||||
.AddParameter("object", _("Object"), "Text")
|
||||
.UseStandardOperatorParameters(
|
||||
"number",
|
||||
gd::ParameterOptions::MakeNewOptions().SetDescription(
|
||||
_("Opacity (0-255)")))
|
||||
.SetFunctionName("SetOpacity")
|
||||
.SetGetter("GetOpacity")
|
||||
.SetHidden();
|
||||
|
||||
// Deprecated
|
||||
obj.AddCondition("Opacity",
|
||||
_("Opacity"),
|
||||
_("Compare the opacity of a Text object, between 0 (fully "
|
||||
"transparent) to 255 (opaque)."),
|
||||
_("the opacity"),
|
||||
"",
|
||||
"res/conditions/opacity24.png",
|
||||
"res/conditions/opacity.png")
|
||||
|
||||
.AddParameter("object", _("Object"), "Text")
|
||||
.UseStandardRelationalOperatorParameters(
|
||||
"number",
|
||||
gd::ParameterOptions::MakeNewOptions().SetDescription(
|
||||
_("Opacity to compare to (0-255)")))
|
||||
.SetFunctionName("GetOpacity")
|
||||
.SetHidden();
|
||||
|
||||
obj.AddAction("SetSmooth",
|
||||
_("Smoothing"),
|
||||
_("Activate or deactivate text smoothing."),
|
||||
@@ -484,37 +327,6 @@ void DeclareTextObjectExtension(gd::PlatformExtension& extension) {
|
||||
.AddParameter("object", _("Object"), "Text")
|
||||
.SetFunctionName("IsUnderlined");
|
||||
|
||||
obj.AddAction("Angle",
|
||||
_("Angle"),
|
||||
_("Modify the angle of a Text object."),
|
||||
_("the angle"),
|
||||
_("Rotation"),
|
||||
"res/actions/rotate24_black.png",
|
||||
"res/actions/rotate_black.png")
|
||||
|
||||
.AddParameter("object", _("Object"), "Text")
|
||||
.UseStandardOperatorParameters(
|
||||
"number",
|
||||
gd::ParameterOptions::MakeNewOptions().SetDescription(
|
||||
_("Angle (in degrees)")))
|
||||
.SetFunctionName("SetAngle")
|
||||
.SetGetter("GetAngle");
|
||||
|
||||
obj.AddCondition("Angle",
|
||||
_("Angle"),
|
||||
_("Compare the value of the angle of a Text object."),
|
||||
_("the angle"),
|
||||
_("Rotation"),
|
||||
"res/conditions/rotate24_black.png",
|
||||
"res/conditions/rotate_black.png")
|
||||
|
||||
.AddParameter("object", _("Object"), "Text")
|
||||
.UseStandardRelationalOperatorParameters(
|
||||
"number",
|
||||
gd::ParameterOptions::MakeNewOptions().SetDescription(
|
||||
_("Angle to compare to (in degrees)")))
|
||||
.SetFunctionName("GetAngle");
|
||||
|
||||
obj.AddCondition("Padding",
|
||||
_("Padding"),
|
||||
_("Compare the number of pixels around a text object. If "
|
||||
@@ -628,6 +440,143 @@ void DeclareTextObjectExtension(gd::PlatformExtension& extension) {
|
||||
"res/actions/textPadding_black.png")
|
||||
.AddParameter("object", _("Object"), "Text");
|
||||
|
||||
obj.AddExpressionAndConditionAndAction("number",
|
||||
"FontSize",
|
||||
_("Font size"),
|
||||
_("the font size of a text object"),
|
||||
_("the font size"),
|
||||
"",
|
||||
"res/conditions/characterSize24.png")
|
||||
.AddParameter("object", _("Object"), "Text")
|
||||
.UseStandardParameters("number", gd::ParameterOptions::MakeNewOptions());
|
||||
|
||||
// Support for deprecated "Size" actions/conditions:
|
||||
obj.AddDuplicatedAction("Size", "Text::SetFontSize").SetHidden();
|
||||
obj.AddDuplicatedCondition("Size", "Text::FontSize").SetHidden();
|
||||
|
||||
// Deprecated
|
||||
obj.AddAction("Angle",
|
||||
_("Angle"),
|
||||
_("Modify the angle of a Text object."),
|
||||
_("the angle"),
|
||||
_("Rotation"),
|
||||
"res/actions/rotate24_black.png",
|
||||
"res/actions/rotate_black.png")
|
||||
|
||||
.AddParameter("object", _("Object"), "Text")
|
||||
.UseStandardOperatorParameters(
|
||||
"number",
|
||||
gd::ParameterOptions::MakeNewOptions().SetDescription(
|
||||
_("Angle (in degrees)")))
|
||||
.SetHidden()
|
||||
.SetFunctionName("SetAngle")
|
||||
.SetGetter("GetAngle");
|
||||
|
||||
// Deprecated
|
||||
obj.AddCondition("Angle",
|
||||
_("Angle"),
|
||||
_("Compare the value of the angle of a Text object."),
|
||||
_("the angle"),
|
||||
_("Rotation"),
|
||||
"res/conditions/rotate24_black.png",
|
||||
"res/conditions/rotate_black.png")
|
||||
|
||||
.AddParameter("object", _("Object"), "Text")
|
||||
.UseStandardRelationalOperatorParameters(
|
||||
"number",
|
||||
gd::ParameterOptions::MakeNewOptions().SetDescription(
|
||||
_("Angle to compare to (in degrees)")))
|
||||
.SetHidden()
|
||||
.SetFunctionName("GetAngle");
|
||||
|
||||
// Deprecated
|
||||
obj.AddCondition("ScaleX",
|
||||
_("Scale on X axis"),
|
||||
_("Compare the scale of the text on the X axis"),
|
||||
_("the scale on the X axis"),
|
||||
"Scale",
|
||||
"res/conditions/scaleWidth24_black.png",
|
||||
"res/conditions/scaleWidth_black.png")
|
||||
|
||||
.AddParameter("object", _("Object"), "Text")
|
||||
.UseStandardRelationalOperatorParameters(
|
||||
"number",
|
||||
gd::ParameterOptions::MakeNewOptions().SetDescription(
|
||||
_("Scale to compare to (1 by default)")))
|
||||
.SetHidden()
|
||||
.SetFunctionName("GetScaleX");
|
||||
|
||||
// Deprecated
|
||||
obj.AddAction(
|
||||
"ScaleX",
|
||||
_("Scale on X axis"),
|
||||
_("Modify the scale of the text on the X axis (default scale is 1)"),
|
||||
_("the scale on the X axis"),
|
||||
_("Scale"),
|
||||
"res/actions/scaleWidth24_black.png",
|
||||
"res/actions/scaleWidth_black.png")
|
||||
|
||||
.AddParameter("object", _("Object"), "Text")
|
||||
.UseStandardOperatorParameters(
|
||||
"number",
|
||||
gd::ParameterOptions::MakeNewOptions().SetDescription(
|
||||
_("Scale (1 by default)")))
|
||||
.SetHidden()
|
||||
.SetFunctionName("SetScaleX");
|
||||
|
||||
// Deprecated
|
||||
obj.AddCondition("ScaleY",
|
||||
_("Scale on Y axis"),
|
||||
_("Compare the scale of the text on the Y axis"),
|
||||
_("the scale on the Y axis"),
|
||||
"Scale",
|
||||
"res/conditions/scaleHeight24_black.png",
|
||||
"res/conditions/scaleHeight_black.png")
|
||||
|
||||
.AddParameter("object", _("Object"), "Text")
|
||||
.UseStandardRelationalOperatorParameters(
|
||||
"number",
|
||||
gd::ParameterOptions::MakeNewOptions().SetDescription(
|
||||
_("Scale to compare to (1 by default)")))
|
||||
.SetHidden()
|
||||
.SetFunctionName("GetScaleY");
|
||||
|
||||
// Deprecated
|
||||
obj.AddAction(
|
||||
"ScaleY",
|
||||
_("Scale on Y axis"),
|
||||
_("Modify the scale of the text on the Y axis (default scale is 1)"),
|
||||
_("the scale on the Y axis"),
|
||||
_("Scale"),
|
||||
"res/actions/scaleHeight24_black.png",
|
||||
"res/actions/scaleHeight_black.png")
|
||||
|
||||
.AddParameter("object", _("Object"), "Text")
|
||||
.UseStandardOperatorParameters(
|
||||
"number",
|
||||
gd::ParameterOptions::MakeNewOptions().SetDescription(
|
||||
_("Scale (1 by default)")))
|
||||
.SetHidden()
|
||||
.SetFunctionName("SetScaleY");
|
||||
|
||||
// Deprecated
|
||||
obj.AddAction(
|
||||
"Scale",
|
||||
_("Scale"),
|
||||
_("Modify the scale of the specified object (default scale is 1)"),
|
||||
_("the scale"),
|
||||
_("Scale"),
|
||||
"res/actions/scale24_black.png",
|
||||
"res/actions/scale_black.png")
|
||||
|
||||
.AddParameter("object", _("Object"), "Text")
|
||||
.UseStandardOperatorParameters(
|
||||
"number",
|
||||
gd::ParameterOptions::MakeNewOptions().SetDescription(
|
||||
_("Scale (1 by default)")))
|
||||
.SetHidden()
|
||||
.SetFunctionName("SetScale");
|
||||
|
||||
// Deprecated
|
||||
obj.AddExpression("ScaleX",
|
||||
_("X Scale of a Text object"),
|
||||
@@ -648,6 +597,43 @@ void DeclareTextObjectExtension(gd::PlatformExtension& extension) {
|
||||
.SetHidden()
|
||||
.SetFunctionName("GetScaleY");
|
||||
|
||||
// Deprecated
|
||||
obj.AddAction("Opacity",
|
||||
_("Text opacity"),
|
||||
_("Change the opacity of a Text. 0 is fully transparent, 255 "
|
||||
"is opaque (default)."),
|
||||
_("the opacity"),
|
||||
"",
|
||||
"res/actions/opacity24.png",
|
||||
"res/actions/opacity.png")
|
||||
|
||||
.AddParameter("object", _("Object"), "Text")
|
||||
.UseStandardOperatorParameters(
|
||||
"number",
|
||||
gd::ParameterOptions::MakeNewOptions().SetDescription(
|
||||
_("Opacity (0-255)")))
|
||||
.SetFunctionName("SetOpacity")
|
||||
.SetGetter("GetOpacity")
|
||||
.SetHidden();
|
||||
|
||||
// Deprecated
|
||||
obj.AddCondition("Opacity",
|
||||
_("Opacity"),
|
||||
_("Compare the opacity of a Text object, between 0 (fully "
|
||||
"transparent) to 255 (opaque)."),
|
||||
_("the opacity"),
|
||||
"",
|
||||
"res/conditions/opacity24.png",
|
||||
"res/conditions/opacity.png")
|
||||
|
||||
.AddParameter("object", _("Object"), "Text")
|
||||
.UseStandardRelationalOperatorParameters(
|
||||
"number",
|
||||
gd::ParameterOptions::MakeNewOptions().SetDescription(
|
||||
_("Opacity to compare to (0-255)")))
|
||||
.SetFunctionName("GetOpacity")
|
||||
.SetHidden();
|
||||
|
||||
// Deprecated
|
||||
obj.AddExpression("Opacity",
|
||||
_("Opacity of a Text object"),
|
||||
@@ -658,30 +644,52 @@ void DeclareTextObjectExtension(gd::PlatformExtension& extension) {
|
||||
.SetFunctionName("GetOpacity")
|
||||
.SetHidden();
|
||||
|
||||
// Deprecated
|
||||
obj.AddExpression("Angle",
|
||||
_("Angle"),
|
||||
_("Angle"),
|
||||
_("Rotation"),
|
||||
"res/actions/rotate_black.png")
|
||||
.AddParameter("object", _("Object"), "Text")
|
||||
.SetHidden()
|
||||
.SetFunctionName("GetAngle");
|
||||
|
||||
obj.AddExpressionAndConditionAndAction("number",
|
||||
"FontSize",
|
||||
_("Font size"),
|
||||
_("the font size of a text object"),
|
||||
_("the font size"),
|
||||
"",
|
||||
"res/conditions/characterSize24.png")
|
||||
// Deprecated
|
||||
obj.AddAction("String",
|
||||
_("Modify the text"),
|
||||
_("Modify the text of a Text object."),
|
||||
_("the text"),
|
||||
"",
|
||||
"res/actions/text24_black.png",
|
||||
"res/actions/text_black.png")
|
||||
.SetHidden()
|
||||
.AddParameter("object", _("Object"), "Text")
|
||||
.UseStandardParameters("number", gd::ParameterOptions::MakeNewOptions());
|
||||
.UseStandardOperatorParameters(
|
||||
"string",
|
||||
gd::ParameterOptions::MakeNewOptions().SetDescription(_("Text")))
|
||||
.SetFunctionName("SetString")
|
||||
.SetGetter("GetString");
|
||||
|
||||
// Support for deprecated "Size" actions/conditions:
|
||||
obj.AddDuplicatedAction("Size", "Text::SetFontSize").SetHidden();
|
||||
obj.AddDuplicatedCondition("Size", "Text::FontSize").SetHidden();
|
||||
// Deprecated
|
||||
obj.AddCondition("String",
|
||||
_("Compare the text"),
|
||||
_("Compare the text of a Text object."),
|
||||
_("the text"),
|
||||
"",
|
||||
"res/conditions/text24_black.png",
|
||||
"res/conditions/text_black.png")
|
||||
.SetHidden()
|
||||
.AddParameter("object", _("Object"), "Text")
|
||||
.UseStandardRelationalOperatorParameters(
|
||||
"string",
|
||||
gd::ParameterOptions::MakeNewOptions().SetDescription(
|
||||
_("Text to compare to")))
|
||||
.SetFunctionName("GetString");
|
||||
|
||||
// Deprecated
|
||||
obj.AddStrExpression(
|
||||
"String", _("Text"), _("Text"), _("Text"), "res/texteicon.png")
|
||||
.AddParameter("object", _("Object"), "Text")
|
||||
.SetHidden()
|
||||
.SetFunctionName("GetString");
|
||||
}
|
||||
|
@@ -29,24 +29,6 @@ class TextObjectJsExtension : public gd::PlatformExtension {
|
||||
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js")
|
||||
.AddIncludeFile(
|
||||
"Extensions/TextObject/textruntimeobject-pixi-renderer.js");
|
||||
GetAllActionsForObject("TextObject::Text")["TextObject::Scale"]
|
||||
.SetFunctionName("setScale")
|
||||
.SetGetter("getScaleMean");
|
||||
GetAllActionsForObject("TextObject::Text")["TextObject::ScaleX"]
|
||||
.SetFunctionName("setScaleX")
|
||||
.SetGetter("getScaleX");
|
||||
GetAllConditionsForObject("TextObject::Text")["TextObject::ScaleX"]
|
||||
.SetFunctionName("getScaleX");
|
||||
GetAllActionsForObject("TextObject::Text")["TextObject::ScaleY"]
|
||||
.SetFunctionName("setScaleY")
|
||||
.SetGetter("getScaleY");
|
||||
GetAllConditionsForObject("TextObject::Text")["TextObject::ScaleY"]
|
||||
.SetFunctionName("getScaleY");
|
||||
GetAllActionsForObject("TextObject::Text")["TextObject::String"]
|
||||
.SetFunctionName("setString")
|
||||
.SetGetter("getString");
|
||||
GetAllConditionsForObject("TextObject::Text")["TextObject::String"]
|
||||
.SetFunctionName("getString");
|
||||
|
||||
GetAllActionsForObject("TextObject::Text")["TextObject::Text::SetFontSize"]
|
||||
.SetFunctionName("setCharacterSize")
|
||||
@@ -56,24 +38,6 @@ class TextObjectJsExtension : public gd::PlatformExtension {
|
||||
GetAllExpressionsForObject("TextObject::Text")["FontSize"]
|
||||
.SetFunctionName("getCharacterSize");
|
||||
|
||||
// Deprecated actions/conditions (use "FontSize"/"SetFontSize" instead):
|
||||
GetAllActionsForObject("TextObject::Text")["TextObject::Size"]
|
||||
.SetFunctionName("setCharacterSize")
|
||||
.SetGetter("getCharacterSize");
|
||||
GetAllConditionsForObject("TextObject::Text")["TextObject::Size"]
|
||||
.SetFunctionName("getCharacterSize");
|
||||
|
||||
GetAllActionsForObject("TextObject::Text")["TextObject::Angle"]
|
||||
.SetFunctionName("setAngle")
|
||||
.SetGetter("getAngle");
|
||||
GetAllConditionsForObject("TextObject::Text")["TextObject::Angle"]
|
||||
.SetFunctionName("getAngle");
|
||||
GetAllActionsForObject("TextObject::Text")["TextObject::Opacity"]
|
||||
.SetFunctionName("setOpacity")
|
||||
.SetGetter("getOpacity");
|
||||
GetAllConditionsForObject("TextObject::Text")["TextObject::Opacity"]
|
||||
.SetFunctionName("getOpacity");
|
||||
|
||||
GetAllActionsForObject("TextObject::Text")["TextObject::SetBold"]
|
||||
.SetFunctionName("setBold");
|
||||
GetAllConditionsForObject("TextObject::Text")["TextObject::IsBold"]
|
||||
@@ -108,16 +72,6 @@ class TextObjectJsExtension : public gd::PlatformExtension {
|
||||
|
||||
GetAllExpressionsForObject("TextObject::Text")["Padding"]
|
||||
.SetFunctionName("getPadding");
|
||||
GetAllExpressionsForObject("TextObject::Text")["ScaleX"]
|
||||
.SetFunctionName("getScaleX");
|
||||
GetAllExpressionsForObject("TextObject::Text")["ScaleY"]
|
||||
.SetFunctionName("getScaleY");
|
||||
GetAllExpressionsForObject("TextObject::Text")["Opacity"]
|
||||
.SetFunctionName("getOpacity");
|
||||
GetAllExpressionsForObject("TextObject::Text")["Angle"]
|
||||
.SetFunctionName("getAngle");
|
||||
GetAllStrExpressionsForObject("TextObject::Text")["String"]
|
||||
.SetFunctionName("getString");
|
||||
|
||||
GetAllActionsForObject("TextObject::Text")["TextObject::ChangeColor"]
|
||||
.SetFunctionName("setColor");
|
||||
@@ -125,15 +79,13 @@ class TextObjectJsExtension : public gd::PlatformExtension {
|
||||
GetAllActionsForObject("TextObject::Text")["TextObject::SetGradient"]
|
||||
.SetFunctionName("setGradient");
|
||||
|
||||
GetAllActionsForObject("TextObject::Text")["TextObject::SetOutline"]
|
||||
.SetFunctionName("setOutline");
|
||||
GetAllActionsForObject("TextObject::Text")["TextObject::Text::SetOutlineEnabled"]
|
||||
.SetFunctionName("setOutlineEnabled");
|
||||
GetAllConditionsForObject("TextObject::Text")["TextObject::Text::IsOutlineEnabled"]
|
||||
.SetFunctionName("isOutlineEnabled");
|
||||
GetAllActionsForObject("TextObject::Text")["TextObject::Text::SetOutlineColor"]
|
||||
.SetFunctionName("setOutlineColor");
|
||||
GetAllExpressionsForObject("TextObject::Text")["TextObject::Text::OutlineThickness"]
|
||||
GetAllExpressionsForObject("TextObject::Text")["OutlineThickness"]
|
||||
.SetFunctionName("getOutlineThickness");
|
||||
GetAllConditionsForObject("TextObject::Text")["TextObject::Text::OutlineThickness"]
|
||||
.SetFunctionName("getOutlineThickness");
|
||||
@@ -141,8 +93,6 @@ class TextObjectJsExtension : public gd::PlatformExtension {
|
||||
.SetFunctionName("setOutlineThickness")
|
||||
.SetGetter("getOutlineThickness");
|
||||
|
||||
GetAllActionsForObject("TextObject::Text")["TextObject::SetShadow"]
|
||||
.SetFunctionName("setShadow");
|
||||
GetAllActionsForObject("TextObject::Text")["TextObject::ShowShadow"]
|
||||
.SetFunctionName("showShadow");
|
||||
GetAllConditionsForObject("TextObject::Text")["TextObject::Text::IsShadowEnabled"]
|
||||
@@ -150,7 +100,7 @@ class TextObjectJsExtension : public gd::PlatformExtension {
|
||||
GetAllActionsForObject("TextObject::Text")["TextObject::Text::SetShadowColor"]
|
||||
.SetFunctionName("setShadowColor");
|
||||
|
||||
GetAllExpressionsForObject("TextObject::Text")["TextObject::Text::ShadowOpacity"]
|
||||
GetAllExpressionsForObject("TextObject::Text")["ShadowOpacity"]
|
||||
.SetFunctionName("getShadowOpacity");
|
||||
GetAllConditionsForObject("TextObject::Text")["TextObject::Text::ShadowOpacity"]
|
||||
.SetFunctionName("getShadowOpacity");
|
||||
@@ -158,7 +108,7 @@ class TextObjectJsExtension : public gd::PlatformExtension {
|
||||
.SetFunctionName("setShadowOpacity")
|
||||
.SetGetter("getShadowOpacity");
|
||||
|
||||
GetAllExpressionsForObject("TextObject::Text")["TextObject::Text::ShadowDistance"]
|
||||
GetAllExpressionsForObject("TextObject::Text")["ShadowDistance"]
|
||||
.SetFunctionName("getShadowDistance");
|
||||
GetAllConditionsForObject("TextObject::Text")["TextObject::Text::ShadowDistance"]
|
||||
.SetFunctionName("getShadowDistance");
|
||||
@@ -166,7 +116,7 @@ class TextObjectJsExtension : public gd::PlatformExtension {
|
||||
.SetFunctionName("setShadowDistance")
|
||||
.SetGetter("getShadowDistance");
|
||||
|
||||
GetAllExpressionsForObject("TextObject::Text")["TextObject::Text::ShadowAngle"]
|
||||
GetAllExpressionsForObject("TextObject::Text")["ShadowAngle"]
|
||||
.SetFunctionName("getShadowAngle");
|
||||
GetAllConditionsForObject("TextObject::Text")["TextObject::Text::ShadowAngle"]
|
||||
.SetFunctionName("getShadowAngle");
|
||||
@@ -174,7 +124,7 @@ class TextObjectJsExtension : public gd::PlatformExtension {
|
||||
.SetFunctionName("setShadowAngle")
|
||||
.SetGetter("getShadowAngle");
|
||||
|
||||
GetAllExpressionsForObject("TextObject::Text")["TextObject::Text::ShadowBlurRadius"]
|
||||
GetAllExpressionsForObject("TextObject::Text")["ShadowBlurRadius"]
|
||||
.SetFunctionName("getShadowBlurRadius");
|
||||
GetAllConditionsForObject("TextObject::Text")["TextObject::Text::ShadowBlurRadius"]
|
||||
.SetFunctionName("getShadowBlurRadius");
|
||||
@@ -182,6 +132,61 @@ class TextObjectJsExtension : public gd::PlatformExtension {
|
||||
.SetFunctionName("setShadowBlurRadius")
|
||||
.SetGetter("getShadowBlurRadius");
|
||||
|
||||
// Deprecated actions/conditions (use "FontSize"/"SetFontSize" instead):
|
||||
GetAllActionsForObject("TextObject::Text")["TextObject::Size"]
|
||||
.SetFunctionName("setCharacterSize")
|
||||
.SetGetter("getCharacterSize");
|
||||
GetAllConditionsForObject("TextObject::Text")["TextObject::Size"]
|
||||
.SetFunctionName("getCharacterSize");
|
||||
|
||||
// Deprecated: now available for all objects.
|
||||
GetAllActionsForObject("TextObject::Text")["TextObject::Angle"]
|
||||
.SetFunctionName("setAngle")
|
||||
.SetGetter("getAngle");
|
||||
GetAllConditionsForObject("TextObject::Text")["TextObject::Angle"]
|
||||
.SetFunctionName("getAngle");
|
||||
GetAllExpressionsForObject("TextObject::Text")["Angle"]
|
||||
.SetFunctionName("getAngle");
|
||||
|
||||
// Deprecated: available through capabilities.
|
||||
GetAllActionsForObject("TextObject::Text")["TextObject::Scale"]
|
||||
.SetFunctionName("setScale")
|
||||
.SetGetter("getScaleMean");
|
||||
GetAllActionsForObject("TextObject::Text")["TextObject::ScaleX"]
|
||||
.SetFunctionName("setScaleX")
|
||||
.SetGetter("getScaleX");
|
||||
GetAllConditionsForObject("TextObject::Text")["TextObject::ScaleX"]
|
||||
.SetFunctionName("getScaleX");
|
||||
GetAllActionsForObject("TextObject::Text")["TextObject::ScaleY"]
|
||||
.SetFunctionName("setScaleY")
|
||||
.SetGetter("getScaleY");
|
||||
GetAllConditionsForObject("TextObject::Text")["TextObject::ScaleY"]
|
||||
.SetFunctionName("getScaleY");
|
||||
GetAllExpressionsForObject("TextObject::Text")["ScaleX"]
|
||||
.SetFunctionName("getScaleX");
|
||||
GetAllExpressionsForObject("TextObject::Text")["ScaleY"]
|
||||
.SetFunctionName("getScaleY");
|
||||
GetAllActionsForObject("TextObject::Text")["TextObject::String"]
|
||||
.SetFunctionName("setString")
|
||||
.SetGetter("getString");
|
||||
GetAllStrExpressionsForObject("TextObject::Text")["String"]
|
||||
.SetFunctionName("getString");
|
||||
GetAllConditionsForObject("TextObject::Text")["TextObject::String"]
|
||||
.SetFunctionName("getString");
|
||||
GetAllExpressionsForObject("TextObject::Text")["Opacity"]
|
||||
.SetFunctionName("getOpacity");
|
||||
GetAllActionsForObject("TextObject::Text")["TextObject::Opacity"]
|
||||
.SetFunctionName("setOpacity")
|
||||
.SetGetter("getOpacity");
|
||||
GetAllConditionsForObject("TextObject::Text")["TextObject::Opacity"]
|
||||
.SetFunctionName("getOpacity");
|
||||
|
||||
// Deprecated: split into several instructions.
|
||||
GetAllActionsForObject("TextObject::Text")["TextObject::SetOutline"]
|
||||
.SetFunctionName("setOutline");
|
||||
GetAllActionsForObject("TextObject::Text")["TextObject::SetShadow"]
|
||||
.SetFunctionName("setShadow");
|
||||
|
||||
// Unimplemented actions and conditions:
|
||||
GetAllActionsForObject("TextObject::Text")["TextObject::Font"]
|
||||
.SetFunctionName("");
|
||||
|
@@ -56,7 +56,8 @@ namespace gdjs {
|
||||
opacity: float = 255;
|
||||
_textAlign: string = 'left';
|
||||
_wrapping: boolean = false;
|
||||
_wrappingWidth: float = 1;
|
||||
// A wrapping of 1 makes games crash on Firefox
|
||||
_wrappingWidth: float = 100;
|
||||
|
||||
_isOutlineEnabled: boolean;
|
||||
_outlineThickness: float;
|
||||
@@ -194,8 +195,8 @@ namespace gdjs {
|
||||
*/
|
||||
extraInitializationFromInitialInstance(initialInstanceData: InstanceData) {
|
||||
if (initialInstanceData.customSize) {
|
||||
this.setWrapping(true);
|
||||
this.setWrappingWidth(initialInstanceData.width);
|
||||
this.setWrapping(true);
|
||||
} else {
|
||||
this.setWrapping(false);
|
||||
}
|
||||
@@ -513,11 +514,15 @@ namespace gdjs {
|
||||
if (width <= 1) {
|
||||
width = 1;
|
||||
}
|
||||
if (this._wrappingWidth === width) return;
|
||||
|
||||
if (this._wrappingWidth === width) {
|
||||
return;
|
||||
}
|
||||
this._wrappingWidth = width;
|
||||
this._renderer.updateStyle();
|
||||
this.invalidateHitboxes();
|
||||
|
||||
if (this._wrapping) {
|
||||
this._renderer.updateStyle();
|
||||
this.invalidateHitboxes();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -1,5 +1,5 @@
|
||||
// @flow
|
||||
|
||||
//@ts-check
|
||||
/// <reference path="../JsExtensionTypes.d.ts" />
|
||||
/// <reference path="helper/TileMapHelper.d.ts" />
|
||||
|
||||
/**
|
||||
@@ -15,20 +15,13 @@
|
||||
* More information on https://github.com/4ian/GDevelop/blob/master/newIDE/README-extensions.md
|
||||
*/
|
||||
|
||||
/*::
|
||||
// Import types to allow Flow to do static type checking on this file.
|
||||
// Extensions declaration are typed using Flow (like the editor), but the files
|
||||
// for the game engine are checked with TypeScript annotations.
|
||||
import { type ObjectsRenderingService, type ObjectsEditorService } from '../JsExtensionTypes.flow.js'
|
||||
*/
|
||||
|
||||
const defineTileMap = function (
|
||||
extension,
|
||||
_ /*: (string) => string */,
|
||||
gd /*: libGDevelop */
|
||||
) {
|
||||
/**
|
||||
* @param {gd.PlatformExtension} extension
|
||||
* @param {(translationSource: string) => string} _
|
||||
* @param {GDNamespace} gd
|
||||
*/
|
||||
const defineTileMap = function (extension, _, gd) {
|
||||
var objectTileMap = new gd.ObjectJsImplementation();
|
||||
// $FlowExpectedError - ignore Flow warning as we're creating an object
|
||||
objectTileMap.updateProperty = function (
|
||||
objectContent,
|
||||
propertyName,
|
||||
@@ -69,7 +62,6 @@ const defineTileMap = function (
|
||||
|
||||
return false;
|
||||
};
|
||||
// $FlowExpectedError - ignore Flow warning as we're creating an object
|
||||
objectTileMap.getProperties = function (objectContent) {
|
||||
var objectProperties = new gd.MapStringPropertyDescriptor();
|
||||
|
||||
@@ -168,7 +160,6 @@ const defineTileMap = function (
|
||||
})
|
||||
);
|
||||
|
||||
// $FlowExpectedError - ignore Flow warning as we're creating an object
|
||||
objectTileMap.updateInitialInstanceProperty = function (
|
||||
objectContent,
|
||||
instance,
|
||||
@@ -179,7 +170,6 @@ const defineTileMap = function (
|
||||
) {
|
||||
return false;
|
||||
};
|
||||
// $FlowExpectedError - ignore Flow warning as we're creating an object
|
||||
objectTileMap.getInitialInstanceProperties = function (
|
||||
content,
|
||||
instance,
|
||||
@@ -608,13 +598,13 @@ const defineTileMap = function (
|
||||
.setFunctionName('setHeight');
|
||||
};
|
||||
|
||||
const defineCollisionMask = function (
|
||||
extension,
|
||||
_ /*: (string) => string */,
|
||||
gd /*: libGDevelop */
|
||||
) {
|
||||
/**
|
||||
* @param {gd.PlatformExtension} extension
|
||||
* @param {(translationSource: string) => string} _
|
||||
* @param {GDNamespace} gd
|
||||
*/
|
||||
const defineCollisionMask = function (extension, _, gd) {
|
||||
var collisionMaskObject = new gd.ObjectJsImplementation();
|
||||
// $FlowExpectedError - ignore Flow warning as we're creating an object
|
||||
collisionMaskObject.updateProperty = function (
|
||||
objectContent,
|
||||
propertyName,
|
||||
@@ -659,7 +649,6 @@ const defineCollisionMask = function (
|
||||
|
||||
return false;
|
||||
};
|
||||
// $FlowExpectedError - ignore Flow warning as we're creating an object
|
||||
collisionMaskObject.getProperties = function (objectContent) {
|
||||
var objectProperties = new gd.MapStringPropertyDescriptor();
|
||||
|
||||
@@ -768,7 +757,6 @@ const defineCollisionMask = function (
|
||||
})
|
||||
);
|
||||
|
||||
// $FlowExpectedError - ignore Flow warning as we're creating an object
|
||||
collisionMaskObject.updateInitialInstanceProperty = function (
|
||||
objectContent,
|
||||
instance,
|
||||
@@ -779,7 +767,6 @@ const defineCollisionMask = function (
|
||||
) {
|
||||
return false;
|
||||
};
|
||||
// $FlowExpectedError - ignore Flow warning as we're creating an object
|
||||
collisionMaskObject.getInitialInstanceProperties = function (
|
||||
content,
|
||||
instance,
|
||||
@@ -1033,6 +1020,7 @@ const defineCollisionMask = function (
|
||||
.setFunctionName('setHeight');
|
||||
};
|
||||
|
||||
/** @type {ExtensionModule} */
|
||||
module.exports = {
|
||||
createExtension: function (
|
||||
_ /*: (string) => string */,
|
||||
@@ -1093,10 +1081,7 @@ module.exports = {
|
||||
* But it is recommended to create tests for the behaviors/objects properties you created
|
||||
* to avoid mistakes.
|
||||
*/
|
||||
runExtensionSanityTests: function (
|
||||
gd /*: libGDevelop */,
|
||||
extension /*: gdPlatformExtension*/
|
||||
) {
|
||||
runExtensionSanityTests: function (gd, extension) {
|
||||
return [];
|
||||
},
|
||||
/**
|
||||
@@ -1104,9 +1089,7 @@ module.exports = {
|
||||
*
|
||||
* ℹ️ Run `node import-GDJS-Runtime.js` (in newIDE/app/scripts) if you make any change.
|
||||
*/
|
||||
registerEditorConfigurations: function (
|
||||
objectsEditorService /*: ObjectsEditorService */
|
||||
) {
|
||||
registerEditorConfigurations: function (objectsEditorService) {
|
||||
objectsEditorService.registerEditorConfiguration(
|
||||
'TileMap::TileMap',
|
||||
objectsEditorService.getDefaultObjectJsImplementationPropertiesEditor({
|
||||
@@ -1125,9 +1108,7 @@ module.exports = {
|
||||
*
|
||||
* ℹ️ Run `node import-GDJS-Runtime.js` (in newIDE/app/scripts) if you make any change.
|
||||
*/
|
||||
registerInstanceRenderers: function (
|
||||
objectsRenderingService /*: ObjectsRenderingService */
|
||||
) {
|
||||
registerInstanceRenderers: function (objectsRenderingService) {
|
||||
const RenderedInstance = objectsRenderingService.RenderedInstance;
|
||||
const PIXI = objectsRenderingService.PIXI;
|
||||
|
||||
@@ -1238,33 +1219,33 @@ module.exports = {
|
||||
updateTileMap() {
|
||||
// Get the tileset resource to use
|
||||
const tilemapAtlasImage = this._associatedObjectConfiguration
|
||||
.getProperties(this.project)
|
||||
.getProperties()
|
||||
.get('tilemapAtlasImage')
|
||||
.getValue();
|
||||
const tilemapJsonFile = this._associatedObjectConfiguration
|
||||
.getProperties(this.project)
|
||||
.getProperties()
|
||||
.get('tilemapJsonFile')
|
||||
.getValue();
|
||||
const tilesetJsonFile = this._associatedObjectConfiguration
|
||||
.getProperties(this.project)
|
||||
.getProperties()
|
||||
.get('tilesetJsonFile')
|
||||
.getValue();
|
||||
const layerIndex = parseInt(
|
||||
this._associatedObjectConfiguration
|
||||
.getProperties(this.project)
|
||||
.getProperties()
|
||||
.get('layerIndex')
|
||||
.getValue(),
|
||||
10
|
||||
);
|
||||
const levelIndex = parseInt(
|
||||
this._associatedObjectConfiguration
|
||||
.getProperties(this.project)
|
||||
.getProperties()
|
||||
.get('levelIndex')
|
||||
.getValue(),
|
||||
10
|
||||
);
|
||||
const displayMode = this._associatedObjectConfiguration
|
||||
.getProperties(this.project)
|
||||
.getProperties()
|
||||
.get('displayMode')
|
||||
.getValue();
|
||||
|
||||
@@ -1306,7 +1287,7 @@ module.exports = {
|
||||
}
|
||||
|
||||
/** @type {TileMapHelper.TileTextureCache} */
|
||||
const textureCache = manager.getOrLoadTextureCache(
|
||||
manager.getOrLoadTextureCache(
|
||||
this._loadTileMapWithCallback.bind(this),
|
||||
(textureName) =>
|
||||
this._pixiResourcesLoader.getPIXITexture(
|
||||
@@ -1357,14 +1338,14 @@ module.exports = {
|
||||
|
||||
async _loadTileMap(tilemapJsonFile, tilesetJsonFile) {
|
||||
try {
|
||||
const tileMapJsonData =
|
||||
await this._pixiResourcesLoader.getResourceJsonData(
|
||||
this._project,
|
||||
tilemapJsonFile
|
||||
);
|
||||
const tileMapJsonData = await this._pixiResourcesLoader.getResourceJsonData(
|
||||
this._project,
|
||||
tilemapJsonFile
|
||||
);
|
||||
|
||||
const tileMap =
|
||||
TilemapHelper.TileMapManager.identify(tileMapJsonData);
|
||||
const tileMap = TilemapHelper.TileMapManager.identify(
|
||||
tileMapJsonData
|
||||
);
|
||||
|
||||
if (tileMap.kind === 'tiled') {
|
||||
const tilesetJsonData = tilesetJsonFile
|
||||
@@ -1521,43 +1502,45 @@ module.exports = {
|
||||
* This is used to reload the Tilemap
|
||||
*/
|
||||
updateTileMap() {
|
||||
// Get the tileset resource to use
|
||||
// This might become useful in the future
|
||||
/*
|
||||
const tilemapAtlasImage = this._associatedObjectConfiguration
|
||||
.getProperties(this.project)
|
||||
.get('tilemapAtlasImage')
|
||||
.getValue();
|
||||
*/
|
||||
const tilemapJsonFile = this._associatedObjectConfiguration
|
||||
.getProperties(this.project)
|
||||
.getProperties()
|
||||
.get('tilemapJsonFile')
|
||||
.getValue();
|
||||
const tilesetJsonFile = this._associatedObjectConfiguration
|
||||
.getProperties(this.project)
|
||||
.getProperties()
|
||||
.get('tilesetJsonFile')
|
||||
.getValue();
|
||||
const collisionMaskTag = this._associatedObjectConfiguration
|
||||
.getProperties(this.project)
|
||||
.getProperties()
|
||||
.get('collisionMaskTag')
|
||||
.getValue();
|
||||
const outlineColor = objectsRenderingService.rgbOrHexToHexNumber(
|
||||
this._associatedObjectConfiguration
|
||||
.getProperties(this.project)
|
||||
.getProperties()
|
||||
.get('outlineColor')
|
||||
.getValue()
|
||||
);
|
||||
const fillColor = objectsRenderingService.rgbOrHexToHexNumber(
|
||||
this._associatedObjectConfiguration
|
||||
.getProperties(this.project)
|
||||
.getProperties()
|
||||
.get('fillColor')
|
||||
.getValue()
|
||||
);
|
||||
const outlineOpacity =
|
||||
this._associatedObjectConfiguration
|
||||
.getProperties(this.project)
|
||||
+this._associatedObjectConfiguration
|
||||
.getProperties()
|
||||
.get('outlineOpacity')
|
||||
.getValue() / 255;
|
||||
const fillOpacity =
|
||||
this._associatedObjectConfiguration
|
||||
.getProperties(this.project)
|
||||
+this._associatedObjectConfiguration
|
||||
.getProperties()
|
||||
.get('fillOpacity')
|
||||
.getValue() / 255;
|
||||
const outlineSize = 1;
|
||||
@@ -1601,14 +1584,14 @@ module.exports = {
|
||||
|
||||
async _loadTileMap(tilemapJsonFile, tilesetJsonFile) {
|
||||
try {
|
||||
const tileMapJsonData =
|
||||
await this._pixiResourcesLoader.getResourceJsonData(
|
||||
this._project,
|
||||
tilemapJsonFile
|
||||
);
|
||||
const tileMapJsonData = await this._pixiResourcesLoader.getResourceJsonData(
|
||||
this._project,
|
||||
tilemapJsonFile
|
||||
);
|
||||
|
||||
const tileMap =
|
||||
TilemapHelper.TileMapManager.identify(tileMapJsonData);
|
||||
const tileMap = TilemapHelper.TileMapManager.identify(
|
||||
tileMapJsonData
|
||||
);
|
||||
|
||||
if (tileMap.kind === 'tiled') {
|
||||
const tilesetJsonData = tilesetJsonFile
|
||||
|
@@ -1,5 +1,5 @@
|
||||
declare namespace PIXI {
|
||||
namespace tilemap {
|
||||
export namespace tilemap {
|
||||
/**
|
||||
* The renderer plugin for canvas. It isn't registered by default.
|
||||
*
|
||||
|
@@ -1,4 +1,5 @@
|
||||
// @flow
|
||||
//@ts-check
|
||||
/// <reference path="../JsExtensionTypes.d.ts" />
|
||||
/**
|
||||
* This is a declaration of an extension for GDevelop 5.
|
||||
*
|
||||
@@ -12,13 +13,6 @@
|
||||
* More information on https://github.com/4ian/GDevelop/blob/master/newIDE/README-extensions.md
|
||||
*/
|
||||
|
||||
/*::
|
||||
// Import types to allow Flow to do static type checking on this file.
|
||||
// Extensions declaration are typed using Flow (like the editor), but the files
|
||||
// for the game engine are checked with TypeScript annotations.
|
||||
import { type ObjectsRenderingService, type ObjectsEditorService } from '../JsExtensionTypes.flow.js'
|
||||
*/
|
||||
|
||||
const easingChoices = JSON.stringify([
|
||||
'linear',
|
||||
'easeInQuad',
|
||||
@@ -57,11 +51,9 @@ const easingChoices = JSON.stringify([
|
||||
'easeTo',
|
||||
]);
|
||||
|
||||
/** @type {ExtensionModule} */
|
||||
module.exports = {
|
||||
createExtension: function (
|
||||
_ /*: (string) => string */,
|
||||
gd /*: libGDevelop */
|
||||
) {
|
||||
createExtension: function (_, gd) {
|
||||
const extension = new gd.PlatformExtension();
|
||||
extension
|
||||
.setExtensionInformation(
|
||||
@@ -387,57 +379,61 @@ module.exports = {
|
||||
.addIncludeFile('Extensions/TweenBehavior/tweentools.js')
|
||||
.setFunctionName('gdjs.evtTools.tween.tweenCameraRotation2');
|
||||
|
||||
extension
|
||||
.addAction(
|
||||
'TweenNumberEffectPropertyTween',
|
||||
_('Tween number effect property'),
|
||||
_('Tweens a number effect property from its current value to a new one.'),
|
||||
_(
|
||||
'Tween the property _PARAM5_ for effect _PARAM4_ of _PARAM3_ to _PARAM2_ with easing _PARAM6_ over _PARAM7_ seconds as _PARAM1_'
|
||||
),
|
||||
_('Scene Tweens'),
|
||||
'JsPlatform/Extensions/tween_behavior24.png',
|
||||
'JsPlatform/Extensions/tween_behavior32.png'
|
||||
)
|
||||
.addCodeOnlyParameter('currentScene', '')
|
||||
.addParameter('identifier', _('Tween Identifier'), 'sceneTween')
|
||||
.addParameter('expression', _('To value'), '', false)
|
||||
.addParameter('layer', _('Layer'), '', true)
|
||||
.addParameter("layerEffectName", _("Effect name"))
|
||||
.addParameter("layerEffectParameterName", _("Property name"))
|
||||
.addParameter('stringWithSelector', _('Easing'), easingChoices, false)
|
||||
.setDefaultValue('linear')
|
||||
.addParameter('expression', _('Duration (in seconds)'), '', false)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile('Extensions/TweenBehavior/TweenManager.js')
|
||||
.addIncludeFile('Extensions/TweenBehavior/tweentools.js')
|
||||
.setFunctionName('gdjs.evtTools.tween.tweenNumberEffectPropertyTween');
|
||||
|
||||
extension
|
||||
.addAction(
|
||||
'TweenColorEffectPropertyTween',
|
||||
_('Tween color effect property'),
|
||||
_('Tweens a color effect property from its current value to a new one.'),
|
||||
_(
|
||||
'Tween the color property _PARAM5_ for effect _PARAM4_ of _PARAM3_ to _PARAM2_ with easing _PARAM6_ over _PARAM7_ seconds as _PARAM1_'
|
||||
),
|
||||
_('Scene Tweens'),
|
||||
'JsPlatform/Extensions/tween_behavior24.png',
|
||||
'JsPlatform/Extensions/tween_behavior32.png'
|
||||
)
|
||||
.addCodeOnlyParameter('currentScene', '')
|
||||
.addParameter('identifier', _('Tween Identifier'), 'sceneTween')
|
||||
.addParameter('color', _('To color'), '', false)
|
||||
.addParameter('layer', _('Layer'), '', true)
|
||||
.addParameter("layerEffectName", _("Effect name"))
|
||||
.addParameter("layerEffectParameterName", _("Property name"))
|
||||
.addParameter('stringWithSelector', _('Easing'), easingChoices, false)
|
||||
.setDefaultValue('linear')
|
||||
.addParameter('expression', _('Duration (in seconds)'), '', false)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile('Extensions/TweenBehavior/TweenManager.js')
|
||||
.addIncludeFile('Extensions/TweenBehavior/tweentools.js')
|
||||
.setFunctionName('gdjs.evtTools.tween.tweenColorEffectPropertyTween');
|
||||
extension
|
||||
.addAction(
|
||||
'TweenNumberEffectPropertyTween',
|
||||
_('Tween number effect property'),
|
||||
_(
|
||||
'Tweens a number effect property from its current value to a new one.'
|
||||
),
|
||||
_(
|
||||
'Tween the property _PARAM5_ for effect _PARAM4_ of _PARAM3_ to _PARAM2_ with easing _PARAM6_ over _PARAM7_ seconds as _PARAM1_'
|
||||
),
|
||||
_('Scene Tweens'),
|
||||
'JsPlatform/Extensions/tween_behavior24.png',
|
||||
'JsPlatform/Extensions/tween_behavior32.png'
|
||||
)
|
||||
.addCodeOnlyParameter('currentScene', '')
|
||||
.addParameter('identifier', _('Tween Identifier'), 'sceneTween')
|
||||
.addParameter('expression', _('To value'), '', false)
|
||||
.addParameter('layer', _('Layer'), '', true)
|
||||
.addParameter('layerEffectName', _('Effect name'))
|
||||
.addParameter('layerEffectParameterName', _('Property name'))
|
||||
.addParameter('stringWithSelector', _('Easing'), easingChoices, false)
|
||||
.setDefaultValue('linear')
|
||||
.addParameter('expression', _('Duration (in seconds)'), '', false)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile('Extensions/TweenBehavior/TweenManager.js')
|
||||
.addIncludeFile('Extensions/TweenBehavior/tweentools.js')
|
||||
.setFunctionName('gdjs.evtTools.tween.tweenNumberEffectPropertyTween');
|
||||
|
||||
extension
|
||||
.addAction(
|
||||
'TweenColorEffectPropertyTween',
|
||||
_('Tween color effect property'),
|
||||
_(
|
||||
'Tweens a color effect property from its current value to a new one.'
|
||||
),
|
||||
_(
|
||||
'Tween the color property _PARAM5_ for effect _PARAM4_ of _PARAM3_ to _PARAM2_ with easing _PARAM6_ over _PARAM7_ seconds as _PARAM1_'
|
||||
),
|
||||
_('Scene Tweens'),
|
||||
'JsPlatform/Extensions/tween_behavior24.png',
|
||||
'JsPlatform/Extensions/tween_behavior32.png'
|
||||
)
|
||||
.addCodeOnlyParameter('currentScene', '')
|
||||
.addParameter('identifier', _('Tween Identifier'), 'sceneTween')
|
||||
.addParameter('color', _('To color'), '', false)
|
||||
.addParameter('layer', _('Layer'), '', true)
|
||||
.addParameter('layerEffectName', _('Effect name'))
|
||||
.addParameter('layerEffectParameterName', _('Property name'))
|
||||
.addParameter('stringWithSelector', _('Easing'), easingChoices, false)
|
||||
.setDefaultValue('linear')
|
||||
.addParameter('expression', _('Duration (in seconds)'), '', false)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile('Extensions/TweenBehavior/TweenManager.js')
|
||||
.addIncludeFile('Extensions/TweenBehavior/tweentools.js')
|
||||
.setFunctionName('gdjs.evtTools.tween.tweenColorEffectPropertyTween');
|
||||
|
||||
extension
|
||||
.addCondition(
|
||||
@@ -597,7 +593,6 @@ module.exports = {
|
||||
|
||||
const tweenBehavior = new gd.BehaviorJsImplementation();
|
||||
|
||||
// $FlowExpectedError - ignore Flow warning as we're creating a behavior
|
||||
tweenBehavior.updateProperty = function (
|
||||
behaviorContent,
|
||||
propertyName,
|
||||
@@ -606,13 +601,11 @@ module.exports = {
|
||||
return false;
|
||||
};
|
||||
|
||||
// $FlowExpectedError - ignore Flow warning as we're creating a behavior
|
||||
tweenBehavior.getProperties = function (behaviorContent) {
|
||||
var behaviorProperties = new gd.MapStringPropertyDescriptor();
|
||||
return behaviorProperties;
|
||||
};
|
||||
|
||||
// $FlowExpectedError - ignore Flow warning as we're creating a behavior
|
||||
tweenBehavior.initializeContent = function (behaviorContent) {};
|
||||
|
||||
const behavior = extension
|
||||
@@ -626,6 +619,7 @@ module.exports = {
|
||||
'',
|
||||
'JsPlatform/Extensions/tween_behavior32.png',
|
||||
'TweenBehavior',
|
||||
// @ts-ignore - TODO: Fix tweenBehavior being an BehaviorJsImplementation instead of an Behavior
|
||||
tweenBehavior,
|
||||
new gd.BehaviorsSharedData()
|
||||
)
|
||||
@@ -926,37 +920,37 @@ module.exports = {
|
||||
.getCodeExtraInformation()
|
||||
.setFunctionName('addObjectPositionZTween');
|
||||
|
||||
behavior
|
||||
.addAction(
|
||||
'AddObjectPositionZTween2',
|
||||
_('Tween object Z position'),
|
||||
_(
|
||||
'Tweens an object Z position (3D objects only) from its current Z position to a new one.'
|
||||
),
|
||||
_(
|
||||
'Tween the Z position of _PARAM0_ to _PARAM4_ with easing _PARAM5_ over _PARAM6_ seconds as _PARAM3_'
|
||||
),
|
||||
_('Position'),
|
||||
'JsPlatform/Extensions/tween_behavior24.png',
|
||||
'JsPlatform/Extensions/tween_behavior32.png'
|
||||
)
|
||||
.addParameter('object', _('Object'), '', false)
|
||||
.addParameter('behavior', _('Behavior'), 'TweenBehavior', false)
|
||||
.addParameter("behavior", _("3D capability"), "Scene3D::Base3DBehavior")
|
||||
.addParameter('identifier', _('Tween Identifier'), 'objectTween')
|
||||
.addParameter('expression', _('To Z'), '', false)
|
||||
.addParameter('stringWithSelector', _('Easing'), easingChoices, false)
|
||||
.setDefaultValue('linear')
|
||||
.addParameter('expression', _('Duration (in seconds)'), '', false)
|
||||
.addParameter(
|
||||
'yesorno',
|
||||
_('Destroy this object when tween finishes'),
|
||||
'',
|
||||
false
|
||||
)
|
||||
.setDefaultValue('no')
|
||||
.getCodeExtraInformation()
|
||||
.setFunctionName('addObjectPositionZTween2');
|
||||
behavior
|
||||
.addAction(
|
||||
'AddObjectPositionZTween2',
|
||||
_('Tween object Z position'),
|
||||
_(
|
||||
'Tweens an object Z position (3D objects only) from its current Z position to a new one.'
|
||||
),
|
||||
_(
|
||||
'Tween the Z position of _PARAM0_ to _PARAM4_ with easing _PARAM5_ over _PARAM6_ seconds as _PARAM3_'
|
||||
),
|
||||
_('Position'),
|
||||
'JsPlatform/Extensions/tween_behavior24.png',
|
||||
'JsPlatform/Extensions/tween_behavior32.png'
|
||||
)
|
||||
.addParameter('object', _('Object'), '', false)
|
||||
.addParameter('behavior', _('Behavior'), 'TweenBehavior', false)
|
||||
.addParameter('behavior', _('3D capability'), 'Scene3D::Base3DBehavior')
|
||||
.addParameter('identifier', _('Tween Identifier'), 'objectTween')
|
||||
.addParameter('expression', _('To Z'), '', false)
|
||||
.addParameter('stringWithSelector', _('Easing'), easingChoices, false)
|
||||
.setDefaultValue('linear')
|
||||
.addParameter('expression', _('Duration (in seconds)'), '', false)
|
||||
.addParameter(
|
||||
'yesorno',
|
||||
_('Destroy this object when tween finishes'),
|
||||
'',
|
||||
false
|
||||
)
|
||||
.setDefaultValue('no')
|
||||
.getCodeExtraInformation()
|
||||
.setFunctionName('addObjectPositionZTween2');
|
||||
|
||||
// deprecated
|
||||
behavior
|
||||
@@ -1111,37 +1105,37 @@ module.exports = {
|
||||
.getCodeExtraInformation()
|
||||
.setFunctionName('addObjectDepthTween');
|
||||
|
||||
behavior
|
||||
.addAction(
|
||||
'AddObjectDepthTween2',
|
||||
_('Tween object depth'),
|
||||
_(
|
||||
'Tweens an object depth (suitable 3D objects only) from its current depth to a new one.'
|
||||
),
|
||||
_(
|
||||
'Tween the depth of _PARAM0_ to _PARAM4_ with easing _PARAM5_ over _PARAM6_ seconds as _PARAM3_'
|
||||
),
|
||||
_('Size'),
|
||||
'JsPlatform/Extensions/tween_behavior24.png',
|
||||
'JsPlatform/Extensions/tween_behavior32.png'
|
||||
)
|
||||
.addParameter('object', _('Object'), '', false)
|
||||
.addParameter('behavior', _('Behavior'), 'TweenBehavior', false)
|
||||
.addParameter("behavior", _("3D capability"), "Scene3D::Base3DBehavior")
|
||||
.addParameter('identifier', _('Tween Identifier'), 'objectTween')
|
||||
.addParameter('expression', _('To depth'), '', false)
|
||||
.addParameter('stringWithSelector', _('Easing'), easingChoices, false)
|
||||
.setDefaultValue('linear')
|
||||
.addParameter('expression', _('Duration (in seconds)'), '', false)
|
||||
.addParameter(
|
||||
'yesorno',
|
||||
_('Destroy this object when tween finishes'),
|
||||
'',
|
||||
false
|
||||
)
|
||||
.setDefaultValue('no')
|
||||
.getCodeExtraInformation()
|
||||
.setFunctionName('addObjectDepthTween2');
|
||||
behavior
|
||||
.addAction(
|
||||
'AddObjectDepthTween2',
|
||||
_('Tween object depth'),
|
||||
_(
|
||||
'Tweens an object depth (suitable 3D objects only) from its current depth to a new one.'
|
||||
),
|
||||
_(
|
||||
'Tween the depth of _PARAM0_ to _PARAM4_ with easing _PARAM5_ over _PARAM6_ seconds as _PARAM3_'
|
||||
),
|
||||
_('Size'),
|
||||
'JsPlatform/Extensions/tween_behavior24.png',
|
||||
'JsPlatform/Extensions/tween_behavior32.png'
|
||||
)
|
||||
.addParameter('object', _('Object'), '', false)
|
||||
.addParameter('behavior', _('Behavior'), 'TweenBehavior', false)
|
||||
.addParameter('behavior', _('3D capability'), 'Scene3D::Base3DBehavior')
|
||||
.addParameter('identifier', _('Tween Identifier'), 'objectTween')
|
||||
.addParameter('expression', _('To depth'), '', false)
|
||||
.addParameter('stringWithSelector', _('Easing'), easingChoices, false)
|
||||
.setDefaultValue('linear')
|
||||
.addParameter('expression', _('Duration (in seconds)'), '', false)
|
||||
.addParameter(
|
||||
'yesorno',
|
||||
_('Destroy this object when tween finishes'),
|
||||
'',
|
||||
false
|
||||
)
|
||||
.setDefaultValue('no')
|
||||
.getCodeExtraInformation()
|
||||
.setFunctionName('addObjectDepthTween2');
|
||||
|
||||
// deprecated
|
||||
behavior
|
||||
@@ -1267,65 +1261,69 @@ module.exports = {
|
||||
.getCodeExtraInformation()
|
||||
.setFunctionName('addObjectAngleTween2');
|
||||
|
||||
behavior
|
||||
.addScopedAction(
|
||||
'AddObjectRotationXTween',
|
||||
_('Tween object rotation on X axis'),
|
||||
_('Tweens an object rotation on X axis from its current angle to a new one.'),
|
||||
_(
|
||||
'Tween the rotation on X axis of _PARAM0_ to _PARAM4_° with easing _PARAM5_ over _PARAM6_ seconds as _PARAM3_'
|
||||
),
|
||||
_('Angle'),
|
||||
'JsPlatform/Extensions/tween_behavior24.png',
|
||||
'JsPlatform/Extensions/tween_behavior32.png'
|
||||
)
|
||||
.addParameter('object', _('Object'), '', false)
|
||||
.addParameter('behavior', _('Behavior'), 'TweenBehavior', false)
|
||||
.addParameter("behavior", _("3D capability"), "Scene3D::Base3DBehavior")
|
||||
.addParameter('identifier', _('Tween Identifier'), 'objectTween')
|
||||
.addParameter('expression', _('To angle (in degrees)'), '', false)
|
||||
.addParameter('stringWithSelector', _('Easing'), easingChoices, false)
|
||||
.setDefaultValue('linear')
|
||||
.addParameter('expression', _('Duration (in seconds)'), '', false)
|
||||
.addParameter(
|
||||
'yesorno',
|
||||
_('Destroy this object when tween finishes'),
|
||||
'',
|
||||
false
|
||||
)
|
||||
.setDefaultValue('no')
|
||||
.getCodeExtraInformation()
|
||||
.setFunctionName('addObjectRotationXTween');
|
||||
behavior
|
||||
.addScopedAction(
|
||||
'AddObjectRotationXTween',
|
||||
_('Tween object rotation on X axis'),
|
||||
_(
|
||||
'Tweens an object rotation on X axis from its current angle to a new one.'
|
||||
),
|
||||
_(
|
||||
'Tween the rotation on X axis of _PARAM0_ to _PARAM4_° with easing _PARAM5_ over _PARAM6_ seconds as _PARAM3_'
|
||||
),
|
||||
_('Angle'),
|
||||
'JsPlatform/Extensions/tween_behavior24.png',
|
||||
'JsPlatform/Extensions/tween_behavior32.png'
|
||||
)
|
||||
.addParameter('object', _('Object'), '', false)
|
||||
.addParameter('behavior', _('Behavior'), 'TweenBehavior', false)
|
||||
.addParameter('behavior', _('3D capability'), 'Scene3D::Base3DBehavior')
|
||||
.addParameter('identifier', _('Tween Identifier'), 'objectTween')
|
||||
.addParameter('expression', _('To angle (in degrees)'), '', false)
|
||||
.addParameter('stringWithSelector', _('Easing'), easingChoices, false)
|
||||
.setDefaultValue('linear')
|
||||
.addParameter('expression', _('Duration (in seconds)'), '', false)
|
||||
.addParameter(
|
||||
'yesorno',
|
||||
_('Destroy this object when tween finishes'),
|
||||
'',
|
||||
false
|
||||
)
|
||||
.setDefaultValue('no')
|
||||
.getCodeExtraInformation()
|
||||
.setFunctionName('addObjectRotationXTween');
|
||||
|
||||
behavior
|
||||
.addScopedAction(
|
||||
'AddObjectRotationYTween',
|
||||
_('Tween object rotation on Y axis'),
|
||||
_('Tweens an object rotation on Y axis from its current angle to a new one.'),
|
||||
_(
|
||||
'Tween the rotation on Y axis of _PARAM0_ to _PARAM4_° with easing _PARAM5_ over _PARAM6_ seconds as _PARAM3_'
|
||||
),
|
||||
_('Angle'),
|
||||
'JsPlatform/Extensions/tween_behavior24.png',
|
||||
'JsPlatform/Extensions/tween_behavior32.png'
|
||||
)
|
||||
.addParameter('object', _('Object'), '', false)
|
||||
.addParameter('behavior', _('Behavior'), 'TweenBehavior', false)
|
||||
.addParameter("behavior", _("3D capability"), "Scene3D::Base3DBehavior")
|
||||
.addParameter('identifier', _('Tween Identifier'), 'objectTween')
|
||||
.addParameter('expression', _('To angle (in degrees)'), '', false)
|
||||
.addParameter('stringWithSelector', _('Easing'), easingChoices, false)
|
||||
.setDefaultValue('linear')
|
||||
.addParameter('expression', _('Duration (in seconds)'), '', false)
|
||||
.addParameter(
|
||||
'yesorno',
|
||||
_('Destroy this object when tween finishes'),
|
||||
'',
|
||||
false
|
||||
)
|
||||
.setDefaultValue('no')
|
||||
.getCodeExtraInformation()
|
||||
.setFunctionName('addObjectRotationYTween');
|
||||
behavior
|
||||
.addScopedAction(
|
||||
'AddObjectRotationYTween',
|
||||
_('Tween object rotation on Y axis'),
|
||||
_(
|
||||
'Tweens an object rotation on Y axis from its current angle to a new one.'
|
||||
),
|
||||
_(
|
||||
'Tween the rotation on Y axis of _PARAM0_ to _PARAM4_° with easing _PARAM5_ over _PARAM6_ seconds as _PARAM3_'
|
||||
),
|
||||
_('Angle'),
|
||||
'JsPlatform/Extensions/tween_behavior24.png',
|
||||
'JsPlatform/Extensions/tween_behavior32.png'
|
||||
)
|
||||
.addParameter('object', _('Object'), '', false)
|
||||
.addParameter('behavior', _('Behavior'), 'TweenBehavior', false)
|
||||
.addParameter('behavior', _('3D capability'), 'Scene3D::Base3DBehavior')
|
||||
.addParameter('identifier', _('Tween Identifier'), 'objectTween')
|
||||
.addParameter('expression', _('To angle (in degrees)'), '', false)
|
||||
.addParameter('stringWithSelector', _('Easing'), easingChoices, false)
|
||||
.setDefaultValue('linear')
|
||||
.addParameter('expression', _('Duration (in seconds)'), '', false)
|
||||
.addParameter(
|
||||
'yesorno',
|
||||
_('Destroy this object when tween finishes'),
|
||||
'',
|
||||
false
|
||||
)
|
||||
.setDefaultValue('no')
|
||||
.getCodeExtraInformation()
|
||||
.setFunctionName('addObjectRotationYTween');
|
||||
|
||||
// deprecated
|
||||
behavior
|
||||
@@ -1700,7 +1698,9 @@ module.exports = {
|
||||
.addScopedAction(
|
||||
'AddNumberEffectPropertyTween',
|
||||
_('Tween number effect property'),
|
||||
_('Tweens a number effect property from its current value to a new one.'),
|
||||
_(
|
||||
'Tweens a number effect property from its current value to a new one.'
|
||||
),
|
||||
_(
|
||||
'Tween the property _PARAM6_ for effect _PARAM5_ of _PARAM0_ to _PARAM4_ with easing _PARAM7_ over _PARAM8_ seconds as _PARAM3_'
|
||||
),
|
||||
@@ -1710,11 +1710,15 @@ module.exports = {
|
||||
)
|
||||
.addParameter('object', _('Object'), '', false)
|
||||
.addParameter('behavior', _('Behavior'), 'TweenBehavior', false)
|
||||
.addParameter("behavior", _("Effect capability"), "EffectCapability::EffectBehavior")
|
||||
.addParameter(
|
||||
'behavior',
|
||||
_('Effect capability'),
|
||||
'EffectCapability::EffectBehavior'
|
||||
)
|
||||
.addParameter('identifier', _('Tween Identifier'), 'objectTween')
|
||||
.addParameter('expression', _('To value'), '', false)
|
||||
.addParameter("objectEffectName", _("Effect name"))
|
||||
.addParameter("objectEffectParameterName", _("Property name"))
|
||||
.addParameter('objectEffectName', _('Effect name'))
|
||||
.addParameter('objectEffectParameterName', _('Property name'))
|
||||
.addParameter('stringWithSelector', _('Easing'), easingChoices, false)
|
||||
.setDefaultValue('linear')
|
||||
.addParameter('expression', _('Duration (in seconds)'), '', false)
|
||||
@@ -1732,7 +1736,9 @@ module.exports = {
|
||||
.addScopedAction(
|
||||
'AddColorEffectPropertyTween',
|
||||
_('Tween color effect property'),
|
||||
_('Tweens a color effect property from its current value to a new one.'),
|
||||
_(
|
||||
'Tweens a color effect property from its current value to a new one.'
|
||||
),
|
||||
_(
|
||||
'Tween the color property _PARAM6_ for effect _PARAM5_ of _PARAM0_ to _PARAM4_ with easing _PARAM7_ over _PARAM8_ seconds as _PARAM3_'
|
||||
),
|
||||
@@ -1742,11 +1748,15 @@ module.exports = {
|
||||
)
|
||||
.addParameter('object', _('Object'), '', false)
|
||||
.addParameter('behavior', _('Behavior'), 'TweenBehavior', false)
|
||||
.addParameter("behavior", _("Effect capability"), "EffectCapability::EffectBehavior")
|
||||
.addParameter(
|
||||
'behavior',
|
||||
_('Effect capability'),
|
||||
'EffectCapability::EffectBehavior'
|
||||
)
|
||||
.addParameter('identifier', _('Tween Identifier'), 'objectTween')
|
||||
.addParameter('color', _('To color'), '', false)
|
||||
.addParameter("objectEffectName", _("Effect name"))
|
||||
.addParameter("objectEffectParameterName", _("Property name"))
|
||||
.addParameter('objectEffectName', _('Effect name'))
|
||||
.addParameter('objectEffectParameterName', _('Property name'))
|
||||
.addParameter('stringWithSelector', _('Easing'), easingChoices, false)
|
||||
.setDefaultValue('linear')
|
||||
.addParameter('expression', _('Duration (in seconds)'), '', false)
|
||||
@@ -1758,7 +1768,7 @@ module.exports = {
|
||||
)
|
||||
.setDefaultValue('no')
|
||||
.getCodeExtraInformation()
|
||||
.setFunctionName('addNumberEffectPropertyTween');
|
||||
.setFunctionName('addColorEffectPropertyTween');
|
||||
|
||||
// deprecated
|
||||
behavior
|
||||
@@ -2088,10 +2098,7 @@ module.exports = {
|
||||
return extension;
|
||||
},
|
||||
|
||||
runExtensionSanityTests: function (
|
||||
gd /*: libGDevelop */,
|
||||
extension /*: gdPlatformExtension*/
|
||||
) {
|
||||
runExtensionSanityTests: function (gd, extension) {
|
||||
return [];
|
||||
},
|
||||
};
|
||||
|
@@ -1,4 +1,6 @@
|
||||
// @flow
|
||||
//@ts-check
|
||||
/// <reference path="../JsExtensionTypes.d.ts" />
|
||||
|
||||
/**
|
||||
* This is a declaration of an extension for GDevelop 5.
|
||||
*
|
||||
@@ -12,34 +14,27 @@
|
||||
* More information on https://github.com/4ian/GDevelop/blob/master/newIDE/README-extensions.md
|
||||
*/
|
||||
|
||||
/*::
|
||||
// Import types to allow Flow to do static type checking on this file.
|
||||
// Extensions declaration are typed using Flow (like the editor), but the files
|
||||
// for the game engine are checked with TypeScript annotations.
|
||||
import { type ObjectsRenderingService, type ObjectsEditorService } from '../JsExtensionTypes.flow.js'
|
||||
*/
|
||||
|
||||
/** @type {ExtensionModule} */
|
||||
module.exports = {
|
||||
createExtension: function (
|
||||
_ /*: (string) => string */,
|
||||
gd /*: libGDevelop */
|
||||
) {
|
||||
createExtension: function (_, gd) {
|
||||
const extension = new gd.PlatformExtension();
|
||||
extension
|
||||
.setExtensionInformation(
|
||||
'Video',
|
||||
_('Video'),
|
||||
_('Provides an object to display a video on the scene. The recommended file format is MPEG4, with H264 video codec and AAC audio codec, to maximize the support of the video on different platform and browsers.'),
|
||||
_(
|
||||
'Provides an object to display a video on the scene. The recommended file format is MPEG4, with H264 video codec and AAC audio codec, to maximize the support of the video on different platform and browsers.'
|
||||
),
|
||||
'Aurélien Vivet',
|
||||
'Open source (MIT License)'
|
||||
)
|
||||
.setCategory('User interface')
|
||||
.setExtensionHelpPath('/objects/video');
|
||||
extension.addInstructionOrExpressionGroupMetadata(_("Video"))
|
||||
.setIcon("JsPlatform/Extensions/videoicon16.png");
|
||||
extension
|
||||
.addInstructionOrExpressionGroupMetadata(_('Video'))
|
||||
.setIcon('JsPlatform/Extensions/videoicon16.png');
|
||||
|
||||
var videoObject = new gd.ObjectJsImplementation();
|
||||
// $FlowExpectedError - ignore Flow warning as we're creating an object
|
||||
videoObject.updateProperty = function (
|
||||
objectContent,
|
||||
propertyName,
|
||||
@@ -64,7 +59,6 @@ module.exports = {
|
||||
|
||||
return false;
|
||||
};
|
||||
// $FlowExpectedError - ignore Flow warning as we're creating an object
|
||||
videoObject.getProperties = function (objectContent) {
|
||||
var objectProperties = new gd.MapStringPropertyDescriptor();
|
||||
|
||||
@@ -104,7 +98,6 @@ module.exports = {
|
||||
})
|
||||
);
|
||||
|
||||
// $FlowExpectedError - ignore Flow warning as we're creating an object
|
||||
videoObject.updateInitialInstanceProperty = function (
|
||||
objectContent,
|
||||
instance,
|
||||
@@ -115,7 +108,6 @@ module.exports = {
|
||||
) {
|
||||
return false;
|
||||
};
|
||||
// $FlowExpectedError - ignore Flow warning as we're creating an object
|
||||
videoObject.getInitialInstanceProperties = function (
|
||||
content,
|
||||
instance,
|
||||
@@ -132,13 +124,14 @@ module.exports = {
|
||||
_('Video'),
|
||||
_('Displays a video.'),
|
||||
'JsPlatform/Extensions/videoicon32.png',
|
||||
// @ts-ignore - TODO: Fix videoObject being an ObjectJsImplementation instead of an ObjectConfiguration
|
||||
videoObject
|
||||
)
|
||||
.setIncludeFile('Extensions/Video/videoruntimeobject.js')
|
||||
.addIncludeFile('Extensions/Video/videoruntimeobject-pixi-renderer.js')
|
||||
.setCategoryFullName(_('User interface'))
|
||||
.addDefaultBehavior('EffectCapability::EffectBehavior')
|
||||
.addDefaultBehavior("OpacityCapability::OpacityBehavior");
|
||||
.addDefaultBehavior('OpacityCapability::OpacityBehavior');
|
||||
|
||||
object
|
||||
.addAction(
|
||||
@@ -533,10 +526,7 @@ module.exports = {
|
||||
* But it is recommended to create tests for the behaviors/objects properties you created
|
||||
* to avoid mistakes.
|
||||
*/
|
||||
runExtensionSanityTests: function (
|
||||
gd /*: libGDevelop */,
|
||||
extension /*: gdPlatformExtension*/
|
||||
) {
|
||||
runExtensionSanityTests: function (gd, extension) {
|
||||
return [];
|
||||
},
|
||||
/**
|
||||
@@ -545,9 +535,7 @@ module.exports = {
|
||||
* ℹ️ Run `node import-GDJS-Runtime.js` (in newIDE/app/scripts) if you make any change.
|
||||
*/
|
||||
|
||||
registerEditorConfigurations: function (
|
||||
objectsEditorService /*: ObjectsEditorService */
|
||||
) {
|
||||
registerEditorConfigurations: function (objectsEditorService) {
|
||||
objectsEditorService.registerEditorConfiguration(
|
||||
'Video::VideoObject',
|
||||
objectsEditorService.getDefaultObjectJsImplementationPropertiesEditor({
|
||||
@@ -560,9 +548,7 @@ module.exports = {
|
||||
*
|
||||
* ℹ️ Run `node import-GDJS-Runtime.js` (in newIDE/app/scripts) if you make any change.
|
||||
*/
|
||||
registerInstanceRenderers: function (
|
||||
objectsRenderingService /*: ObjectsRenderingService */
|
||||
) {
|
||||
registerInstanceRenderers: function (objectsRenderingService) {
|
||||
const RenderedInstance = objectsRenderingService.RenderedInstance;
|
||||
const PIXI = objectsRenderingService.PIXI;
|
||||
|
||||
@@ -570,7 +556,7 @@ module.exports = {
|
||||
* Renderer for instances of VideoObject inside the IDE.
|
||||
*/
|
||||
class RenderedVideoObjectInstance extends RenderedInstance {
|
||||
constructor (
|
||||
constructor(
|
||||
project,
|
||||
layout,
|
||||
instance,
|
||||
@@ -606,11 +592,7 @@ module.exports = {
|
||||
/**
|
||||
* Return the path to the thumbnail of the specified object.
|
||||
*/
|
||||
static getThumbnail(
|
||||
project,
|
||||
resourcesLoader,
|
||||
objectConfiguration
|
||||
) {
|
||||
static getThumbnail(project, resourcesLoader, objectConfiguration) {
|
||||
return 'JsPlatform/Extensions/videoicon24.png';
|
||||
}
|
||||
|
||||
@@ -647,14 +629,13 @@ module.exports = {
|
||||
that._pixiObject.texture.on('error', function () {
|
||||
that._pixiObject.texture.off('error', this);
|
||||
|
||||
that._pixiObject.texture =
|
||||
that._pixiResourcesLoader.getInvalidPIXITexture();
|
||||
that._pixiObject.texture = that._pixiResourcesLoader.getInvalidPIXITexture();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Update opacity
|
||||
const opacity = this._associatedObjectConfiguration
|
||||
const opacity = +this._associatedObjectConfiguration
|
||||
.getProperties()
|
||||
.get('Opacity')
|
||||
.getValue();
|
||||
|
@@ -7,7 +7,11 @@
|
||||
#include "GDCore/CommonTools.h"
|
||||
#include "GDCore/Events/Tools/EventsCodeNameMangler.h"
|
||||
#include "GDCore/Extensions/Metadata/MultipleInstructionMetadata.h"
|
||||
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
|
||||
#include "GDCore/Extensions/Metadata/ObjectMetadata.h"
|
||||
#include "GDCore/Extensions/PlatformExtension.h"
|
||||
#include "GDCore/IDE/Project/ArbitraryObjectsWorker.h"
|
||||
#include "GDCore/IDE/WholeProjectBrowser.h"
|
||||
#include "GDCore/Project/CustomBehavior.h"
|
||||
#include "GDCore/Project/CustomBehaviorsSharedData.h"
|
||||
#include "GDCore/Project/EventsBasedObject.h"
|
||||
@@ -125,8 +129,6 @@ gd::ObjectMetadata &MetadataDeclarationHelper::DeclareObjectMetadata(
|
||||
// Note: EventsFunctionsExtension should be used instead of
|
||||
// PlatformExtension but this line will be removed soon.
|
||||
.SetCategoryFullName(extension.GetCategory())
|
||||
// Update Project::CreateObject when default behaviors are added.
|
||||
.AddDefaultBehavior("EffectCapability::EffectBehavior")
|
||||
.AddDefaultBehavior("ResizableCapability::ResizableBehavior")
|
||||
.AddDefaultBehavior("ScalableCapability::ScalableBehavior")
|
||||
.AddDefaultBehavior("FlippableCapability::FlippableBehavior");
|
||||
@@ -136,8 +138,13 @@ gd::ObjectMetadata &MetadataDeclarationHelper::DeclareObjectMetadata(
|
||||
.AddDefaultBehavior("Scene3D::Base3DBehavior");
|
||||
}
|
||||
else {
|
||||
objectMetadata.AddDefaultBehavior("EffectCapability::EffectBehavior");
|
||||
objectMetadata.AddDefaultBehavior("OpacityCapability::OpacityBehavior");
|
||||
}
|
||||
if (eventsBasedObject.IsTextContainer()) {
|
||||
objectMetadata
|
||||
.AddDefaultBehavior("TextContainerCapability::TextContainerBehavior");
|
||||
}
|
||||
|
||||
// TODO EBO Use full type to identify object to avoid collision.
|
||||
// Objects are identified by their name alone.
|
||||
@@ -1510,7 +1517,7 @@ gd::BehaviorMetadata &MetadataDeclarationHelper::GenerateBehaviorMetadata(
|
||||
}
|
||||
|
||||
gd::ObjectMetadata &MetadataDeclarationHelper::GenerateObjectMetadata(
|
||||
const gd::Project &project, gd::PlatformExtension &extension,
|
||||
gd::Project &project, gd::PlatformExtension &extension,
|
||||
const gd::EventsFunctionsExtension &eventsFunctionsExtension,
|
||||
const gd::EventsBasedObject &eventsBasedObject,
|
||||
std::map<gd::String, gd::String> &objectMethodMangledNames) {
|
||||
@@ -1545,7 +1552,58 @@ gd::ObjectMetadata &MetadataDeclarationHelper::GenerateObjectMetadata(
|
||||
instructionOrExpression.SetPrivate();
|
||||
}
|
||||
|
||||
UpdateCustomObjectDefaultBehaviors(project, objectMetadata);
|
||||
|
||||
return objectMetadata;
|
||||
}
|
||||
|
||||
class DefaultBehaviorUpdater : public gd::ArbitraryObjectsWorker {
|
||||
|
||||
public:
|
||||
DefaultBehaviorUpdater(const gd::Project &project_,
|
||||
const gd::ObjectMetadata &objectMetadata_)
|
||||
: project(project_), objectMetadata(objectMetadata_){};
|
||||
virtual ~DefaultBehaviorUpdater(){};
|
||||
|
||||
private:
|
||||
void DoVisitObject(gd::Object &object) override {
|
||||
|
||||
if (object.GetType() != objectMetadata.GetName()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto &defaultBehaviorTypes = objectMetadata.GetDefaultBehaviors();
|
||||
for (const gd::String &behaviorName : object.GetAllBehaviorNames()) {
|
||||
const auto &behavior = object.GetBehavior(behaviorName);
|
||||
if (behavior.IsDefaultBehavior()) {
|
||||
object.RemoveBehavior(behaviorName);
|
||||
}
|
||||
}
|
||||
auto &platform = project.GetCurrentPlatform();
|
||||
for (const gd::String &behaviorType : defaultBehaviorTypes) {
|
||||
auto &behaviorMetadata =
|
||||
gd::MetadataProvider::GetBehaviorMetadata(platform, behaviorType);
|
||||
if (MetadataProvider::IsBadBehaviorMetadata(behaviorMetadata)) {
|
||||
gd::LogWarning("Object: " + object.GetType() +
|
||||
" has an unknown default behavior: " + behaviorType);
|
||||
continue;
|
||||
}
|
||||
const gd::String &behaviorName = behaviorMetadata.GetDefaultName();
|
||||
auto *behavior =
|
||||
object.AddNewBehavior(project, behaviorType, behaviorName);
|
||||
behavior->SetDefaultBehavior(true);
|
||||
}
|
||||
}
|
||||
|
||||
const gd::Project &project;
|
||||
const gd::ObjectMetadata &objectMetadata;
|
||||
};
|
||||
|
||||
void MetadataDeclarationHelper::UpdateCustomObjectDefaultBehaviors(
|
||||
gd::Project &project, const gd::ObjectMetadata &objectMetadata) {
|
||||
gd::WholeProjectBrowser projectBrowser;
|
||||
auto defaultBehaviorUpdater = DefaultBehaviorUpdater(project, objectMetadata);
|
||||
projectBrowser.ExposeObjects(project, defaultBehaviorUpdater);
|
||||
}
|
||||
|
||||
} // namespace gdjs
|
@@ -61,7 +61,7 @@ public:
|
||||
std::map<gd::String, gd::String> &behaviorMethodMangledNames);
|
||||
|
||||
static gd::ObjectMetadata &GenerateObjectMetadata(
|
||||
const gd::Project &project, gd::PlatformExtension &extension,
|
||||
gd::Project &project, gd::PlatformExtension &extension,
|
||||
const gd::EventsFunctionsExtension &eventsFunctionsExtension,
|
||||
const gd::EventsBasedObject &eventsBasedObject,
|
||||
std::map<gd::String, gd::String> &objectMethodMangledNames);
|
||||
@@ -313,6 +313,10 @@ private:
|
||||
gd::MultipleInstructionMetadata &multipleInstructionMetadata,
|
||||
const int userDefinedFirstParameterIndex);
|
||||
|
||||
static void
|
||||
UpdateCustomObjectDefaultBehaviors(gd::Project &project,
|
||||
const gd::ObjectMetadata &objectMetadata);
|
||||
|
||||
static gd::String RemoveTrailingDot(const gd::String &description);
|
||||
|
||||
static gd::String
|
||||
|
@@ -109,6 +109,19 @@ gd::String ObjectCodeGenerator::GenerateRuntimeObjectCompleteCode(
|
||||
}
|
||||
|
||||
return updateFromObjectCode;
|
||||
},
|
||||
// generateTextContainerCode
|
||||
[&]() {
|
||||
return gd::String(R"jscode_template(
|
||||
// gdjs.TextContainer interface implementation
|
||||
_text = '';
|
||||
getText() {
|
||||
return this._text;
|
||||
}
|
||||
setText(text) {
|
||||
this._text = text;
|
||||
}
|
||||
)jscode_template");
|
||||
});
|
||||
}
|
||||
|
||||
@@ -119,7 +132,8 @@ gd::String ObjectCodeGenerator::GenerateRuntimeObjectTemplateCode(
|
||||
std::function<gd::String()> generateInitializePropertiesCode,
|
||||
std::function<gd::String()> generatePropertiesCode,
|
||||
std::function<gd::String()> generateMethodsCode,
|
||||
std::function<gd::String()> generateUpdateFromObjectDataCode) {
|
||||
std::function<gd::String()> generateUpdateFromObjectDataCode,
|
||||
std::function<gd::String()> generateTextContainerCode) {
|
||||
return gd::String(R"jscode_template(
|
||||
CODE_NAMESPACE = CODE_NAMESPACE || {};
|
||||
|
||||
@@ -149,6 +163,8 @@ CODE_NAMESPACE.RUNTIME_OBJECT_CLASSNAME = class RUNTIME_OBJECT_CLASSNAME extends
|
||||
|
||||
// Properties:
|
||||
PROPERTIES_CODE
|
||||
|
||||
TEXT_CONTAINER_CODE
|
||||
}
|
||||
|
||||
// Methods:
|
||||
@@ -168,6 +184,7 @@ gdjs.registerObject("EXTENSION_NAME::OBJECT_NAME", CODE_NAMESPACE.RUNTIME_OBJECT
|
||||
generateInitializePropertiesCode())
|
||||
.FindAndReplace("UPDATE_FROM_OBJECT_DATA_CODE", generateUpdateFromObjectDataCode())
|
||||
.FindAndReplace("PROPERTIES_CODE", generatePropertiesCode())
|
||||
.FindAndReplace("TEXT_CONTAINER_CODE", eventsBasedObject.IsTextContainer() ? generateTextContainerCode() : "")
|
||||
.FindAndReplace("METHODS_CODE", generateMethodsCode());
|
||||
;
|
||||
}
|
||||
|
@@ -74,7 +74,8 @@ class ObjectCodeGenerator {
|
||||
std::function<gd::String()> generateInitializePropertiesCode,
|
||||
std::function<gd::String()> generateMethodsCode,
|
||||
std::function<gd::String()> generatePropertiesCode,
|
||||
std::function<gd::String()> generateUpdateFromObjectDataCode);
|
||||
std::function<gd::String()> generateUpdateFromObjectDataCode,
|
||||
std::function<gd::String()> generateTextContainerCode);
|
||||
|
||||
gd::String GenerateRuntimeObjectPropertyTemplateCode(
|
||||
const gd::EventsBasedObject& eventsBasedObject,
|
||||
|
@@ -18,7 +18,7 @@ namespace gdjs {
|
||||
}
|
||||
|
||||
/**
|
||||
* A behavior that forwards the Animatable interface to its object.
|
||||
* A behavior that forwards the TextContainer interface to its object.
|
||||
*/
|
||||
export class TextContainerBehavior
|
||||
extends gdjs.RuntimeBehavior
|
||||
|
@@ -29,8 +29,8 @@
|
||||
"check-types": "tsc",
|
||||
"build": "node scripts/build.js",
|
||||
"test": "cd tests && npm run test-benchmark",
|
||||
"format": "prettier --write \"Runtime/**/*.ts\" \"../Extensions/**/*.ts\" \"../Extensions/**/*.spec.js\"",
|
||||
"check-format": "prettier --list-different \"Runtime/**/*.ts\" \"../Extensions/**/*.ts\" \"../Extensions/**/*.spec.js\"",
|
||||
"format": "prettier --write \"Runtime/**/*.ts\" \"../Extensions/**/*.ts\" \"../Extensions/**/JsExtension.js\" \"../Extensions/**/*.spec.js\"",
|
||||
"check-format": "prettier --list-different \"Runtime/**/*.ts\" \"../Extensions/**/*.ts\" \"../Extensions/**/JsExtension.js\" \"../Extensions/**/*.spec.js\"",
|
||||
"generate-doc": "typedoc --options docs/typedoc.json"
|
||||
}
|
||||
}
|
||||
|
@@ -1386,8 +1386,8 @@ interface ParameterOptions {
|
||||
interface AbstractFunctionMetadata {
|
||||
[Ref] AbstractFunctionMetadata AddParameter([Const] DOMString type,
|
||||
[Const] DOMString description,
|
||||
[Const] DOMString optionalObjectType,
|
||||
boolean parameterIsOptional);
|
||||
[Const] optional DOMString optionalObjectType,
|
||||
optional boolean parameterIsOptional);
|
||||
[Ref] AbstractFunctionMetadata AddCodeOnlyParameter(
|
||||
[Const] DOMString type, [Const] DOMString supplementaryInformation);
|
||||
[Ref] AbstractFunctionMetadata SetDefaultValue([Const] DOMString defaultValue);
|
||||
@@ -1437,8 +1437,8 @@ interface InstructionMetadata {
|
||||
[Ref] InstructionMetadata SetRelevantForCustomObjectEventsOnly();
|
||||
[Ref] InstructionMetadata AddParameter([Const] DOMString type,
|
||||
[Const] DOMString description,
|
||||
[Const] DOMString optionalObjectType,
|
||||
boolean parameterIsOptional);
|
||||
[Const] optional DOMString optionalObjectType,
|
||||
optional boolean parameterIsOptional);
|
||||
[Ref] InstructionMetadata AddCodeOnlyParameter(
|
||||
[Const] DOMString type, [Const] DOMString supplementaryInformation);
|
||||
[Ref] InstructionMetadata SetDefaultValue([Const] DOMString defaultValue);
|
||||
@@ -1502,8 +1502,8 @@ interface ExpressionMetadata {
|
||||
[Ref] ExpressionMetadata AddParameter(
|
||||
[Const] DOMString type,
|
||||
[Const] DOMString description,
|
||||
[Const] DOMString optionalObjectType,
|
||||
boolean parameterIsOptional);
|
||||
[Const] optional DOMString optionalObjectType,
|
||||
optional boolean parameterIsOptional);
|
||||
[Ref] ExpressionMetadata AddCodeOnlyParameter(
|
||||
[Const] DOMString type, [Const] DOMString supplementaryInformation);
|
||||
[Ref] ExpressionMetadata SetDefaultValue([Const] DOMString defaultValue);
|
||||
@@ -1524,8 +1524,8 @@ ExpressionMetadata implements AbstractFunctionMetadata;
|
||||
interface MultipleInstructionMetadata {
|
||||
[Ref] MultipleInstructionMetadata AddParameter([Const] DOMString type,
|
||||
[Const] DOMString description,
|
||||
[Const] DOMString optionalObjectType,
|
||||
boolean parameterIsOptional);
|
||||
[Const] optional DOMString optionalObjectType,
|
||||
optional boolean parameterIsOptional);
|
||||
[Ref] MultipleInstructionMetadata AddCodeOnlyParameter(
|
||||
[Const] DOMString type, [Const] DOMString supplementaryInformation);
|
||||
[Ref] MultipleInstructionMetadata SetDefaultValue([Const] DOMString defaultValue);
|
||||
@@ -2790,6 +2790,8 @@ interface EventsBasedObject {
|
||||
|
||||
[Ref] EventsBasedObject MarkAsRenderedIn3D(boolean isRenderedIn3D);
|
||||
boolean IsRenderedIn3D();
|
||||
[Ref] EventsBasedObject MarkAsTextContainer(boolean isTextContainer);
|
||||
boolean IsTextContainer();
|
||||
|
||||
[Const, Value] DOMString STATIC_GetPropertyActionName([Const] DOMString propertyName);
|
||||
[Const, Value] DOMString STATIC_GetPropertyConditionName([Const] DOMString propertyName);
|
||||
@@ -3608,7 +3610,7 @@ interface MetadataDeclarationHelper {
|
||||
[Ref] MapStringString behaviorMethodMangledNames);
|
||||
|
||||
[Ref] ObjectMetadata STATIC_GenerateObjectMetadata(
|
||||
[Const, Ref] Project project,
|
||||
[Ref] Project project,
|
||||
[Ref] PlatformExtension extension,
|
||||
[Const, Ref] EventsFunctionsExtension eventsFunctionsExtension,
|
||||
[Const, Ref] EventsBasedObject eventsBasedObject,
|
||||
|
@@ -81,6 +81,7 @@ target_link_libraries(GD "-s MODULARIZE=1")
|
||||
target_link_libraries(GD "-s EXPORT_NAME=\"initializeGDevelopJs\"") # Global function name for browsers
|
||||
target_link_libraries(GD "-s TOTAL_MEMORY=48MB") # Get some initial memory size that is a bit bigger than the default.
|
||||
target_link_libraries(GD "-s ALLOW_MEMORY_GROWTH=1")
|
||||
target_link_libraries(GD "-s NODEJS_CATCH_EXIT=0") # Don't print the entire GDCore code on error when running in node
|
||||
target_link_libraries(GD "-s ERROR_ON_UNDEFINED_SYMBOLS=0")
|
||||
target_link_libraries(GD "-s \"EXPORTED_FUNCTIONS=['_free']\"")
|
||||
|
||||
|
@@ -1022,7 +1022,7 @@ describe('MetadataDeclarationHelper', () => {
|
||||
},
|
||||
});
|
||||
|
||||
it('can create metadata for custom object default instructions and expressions', () => {
|
||||
it('can create metadata for custom object default capabilities', () => {
|
||||
const extension = new gd.PlatformExtension();
|
||||
const project = new gd.Project();
|
||||
|
||||
@@ -1048,11 +1048,22 @@ describe('MetadataDeclarationHelper', () => {
|
||||
expect(extension.getExtensionObjectsTypes().at(0)).toBe('MyObject');
|
||||
const objectMetadata = extension.getObjectMetadata('MyObject');
|
||||
|
||||
// The capabilities replaced the deprecated instructions below.
|
||||
expectArray(
|
||||
objectMetadata.getDefaultBehaviors().toNewVectorString().toJSArray()
|
||||
).toContainAll([
|
||||
"ResizableCapability::ResizableBehavior",
|
||||
"ScalableCapability::ScalableBehavior",
|
||||
"FlippableCapability::FlippableBehavior",
|
||||
"OpacityCapability::OpacityBehavior",
|
||||
"EffectCapability::EffectBehavior",
|
||||
]);
|
||||
|
||||
expectArray(objectMetadata.getAllActions().keys().toJSArray()).toContainAll(
|
||||
[
|
||||
// Private
|
||||
'MyObject::SetRotationCenter',
|
||||
// Public
|
||||
// Deprecated
|
||||
'MyObject::Width',
|
||||
'Width',
|
||||
'MyObject::Height',
|
||||
@@ -1078,6 +1089,7 @@ describe('MetadataDeclarationHelper', () => {
|
||||
expectArray(
|
||||
objectMetadata.getAllConditions().keys().toJSArray()
|
||||
).toContainAll([
|
||||
// Deprecated
|
||||
'MyObject::ScaleX',
|
||||
'MyObject::ScaleY',
|
||||
'MyObject::FlippedX',
|
||||
@@ -1089,7 +1101,9 @@ describe('MetadataDeclarationHelper', () => {
|
||||
|
||||
expectArray(
|
||||
objectMetadata.getAllExpressions().keys().toJSArray()
|
||||
).toContainAll(['ScaleX', 'ScaleY', 'Opacity']);
|
||||
).toContainAll([
|
||||
// Deprecated
|
||||
'ScaleX', 'ScaleY', 'Opacity']);
|
||||
|
||||
expectArray(
|
||||
objectMetadata.getAllStrExpressions().keys().toJSArray()
|
||||
@@ -1099,6 +1113,53 @@ describe('MetadataDeclarationHelper', () => {
|
||||
project.delete();
|
||||
});
|
||||
|
||||
it('can create metadata for custom object with all capabilities', () => {
|
||||
const extension = new gd.PlatformExtension();
|
||||
const project = new gd.Project();
|
||||
|
||||
const eventExtension = project.insertNewEventsFunctionsExtension(
|
||||
'MyExtension',
|
||||
0
|
||||
);
|
||||
const eventsBasedObject = eventExtension
|
||||
.getEventsBasedObjects()
|
||||
.insertNew('MyObject', 0);
|
||||
eventsBasedObject.markAsRenderedIn3D(true);
|
||||
// TODO Uncomment when the feature is done.
|
||||
// eventsBasedObject.markAsAnimatable(true);
|
||||
eventsBasedObject.markAsTextContainer(true);
|
||||
|
||||
const objectMethodMangledNames = new gd.MapStringString();
|
||||
gd.MetadataDeclarationHelper.generateObjectMetadata(
|
||||
project,
|
||||
extension,
|
||||
eventExtension,
|
||||
eventsBasedObject,
|
||||
objectMethodMangledNames
|
||||
);
|
||||
objectMethodMangledNames.delete();
|
||||
|
||||
expect(extension.getExtensionObjectsTypes().size()).toBe(1);
|
||||
expect(extension.getExtensionObjectsTypes().at(0)).toBe('MyObject');
|
||||
const objectMetadata = extension.getObjectMetadata('MyObject');
|
||||
|
||||
expectArray(
|
||||
objectMetadata.getDefaultBehaviors().toNewVectorString().toJSArray()
|
||||
).toContainAll([
|
||||
"ResizableCapability::ResizableBehavior",
|
||||
"ScalableCapability::ScalableBehavior",
|
||||
"FlippableCapability::FlippableBehavior",
|
||||
// No effect nor opacity capabilities for 3D objects.
|
||||
"Scene3D::Base3DBehavior",
|
||||
// TODO Uncomment when the feature is done.
|
||||
// "AnimatableCapability::AnimatableBehavior",
|
||||
"TextContainerCapability::TextContainerBehavior",
|
||||
]);
|
||||
|
||||
extension.delete();
|
||||
project.delete();
|
||||
});
|
||||
|
||||
it('can create metadata for object actions', () => {
|
||||
const extension = new gd.PlatformExtension();
|
||||
const project = new gd.Project();
|
||||
|
18
GDevelop.js/package-lock.json
generated
18
GDevelop.js/package-lock.json
generated
@@ -8,9 +8,6 @@
|
||||
"name": "GDevelop.js",
|
||||
"version": "0.0.1",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"prettier": "^2.1.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.3.1",
|
||||
"extend": "^2.0.1",
|
||||
@@ -25,6 +22,7 @@
|
||||
"grunt-shell": "^2.1.0",
|
||||
"grunt-string-replace": "^1.3.1",
|
||||
"jest": "^29.7.0",
|
||||
"prettier": "^3.2.2",
|
||||
"shelljs": "^0.8.4",
|
||||
"webidl-tools": "github:4ian/webidl-tools#348f9c03afc9d8f278efccdd74543e265a41fd11"
|
||||
}
|
||||
@@ -7545,14 +7543,18 @@
|
||||
}
|
||||
},
|
||||
"node_modules/prettier": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.1.2.tgz",
|
||||
"integrity": "sha512-16c7K+x4qVlJg9rEbXl7HEGmQyZlG4R9AgP+oHKRMsMsuk8s+ATStlf1NpDqyBI1HpVyfjLOeMhH2LvuNvV5Vg==",
|
||||
"version": "3.2.2",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.2.tgz",
|
||||
"integrity": "sha512-HTByuKZzw7utPiDO523Tt2pLtEyK7OibUD9suEJQrPUCYQqrHr74GGX6VidMrovbf/I50mPqr8j/II6oBAuc5A==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"prettier": "bin-prettier.js"
|
||||
"prettier": "bin/prettier.cjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.13.0"
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/prettier/prettier?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/pretty-bytes": {
|
||||
|
@@ -33,6 +33,7 @@
|
||||
"grunt-shell": "^2.1.0",
|
||||
"grunt-string-replace": "^1.3.1",
|
||||
"jest": "^29.7.0",
|
||||
"prettier": "^3.2.2",
|
||||
"shelljs": "^0.8.4",
|
||||
"webidl-tools": "github:4ian/webidl-tools#348f9c03afc9d8f278efccdd74543e265a41fd11"
|
||||
},
|
||||
@@ -45,8 +46,5 @@
|
||||
"<rootDir>/emsdk/",
|
||||
"<rootDir>/node_modules/"
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"prettier": "^2.1.2"
|
||||
}
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// @ts-check
|
||||
import { readFileSync, writeFileSync } from 'fs';
|
||||
import { dirname } from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { readFileSync, writeFileSync } from 'node:fs';
|
||||
import { dirname } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
const bindingsFile = readFileSync(
|
||||
@@ -9,6 +9,69 @@ const bindingsFile = readFileSync(
|
||||
'utf-8'
|
||||
);
|
||||
|
||||
/** @type {Record<string, {returnType: string, inputType?: string}>} */
|
||||
const castFunctions = {
|
||||
StandardEvent: { inputType: 'Event', returnType: 'StandardEvent' },
|
||||
RepeatEvent: { inputType: 'Event', returnType: 'RepeatEvent' },
|
||||
WhileEvent: { inputType: 'Event', returnType: 'WhileEvent' },
|
||||
ForEachEvent: { inputType: 'Event', returnType: 'ForEachEvent' },
|
||||
ForEachChildVariableEvent: {
|
||||
inputType: 'Event',
|
||||
returnType: 'ForEachChildVariableEvent',
|
||||
},
|
||||
CommentEvent: { inputType: 'Event', returnType: 'CommentEvent' },
|
||||
GroupEvent: { inputType: 'Event', returnType: 'GroupEvent' },
|
||||
LinkEvent: { inputType: 'Event', returnType: 'LinkEvent' },
|
||||
JsCodeEvent: { inputType: 'Event', returnType: 'JsCodeEvent' },
|
||||
|
||||
Platform: { inputType: 'JsPlatform', returnType: 'Platform' },
|
||||
|
||||
SpriteConfiguration: {
|
||||
inputType: 'ObjectConfiguration',
|
||||
returnType: 'SpriteObject',
|
||||
},
|
||||
TiledSpriteConfiguration: {
|
||||
inputType: 'ObjectConfiguration',
|
||||
returnType: 'TiledSpriteObject',
|
||||
},
|
||||
PanelSpriteConfiguration: {
|
||||
inputType: 'ObjectConfiguration',
|
||||
returnType: 'PanelSpriteObject',
|
||||
},
|
||||
TextObjectConfiguration: {
|
||||
inputType: 'ObjectConfiguration',
|
||||
returnType: 'TextObject',
|
||||
},
|
||||
ShapePainterConfiguration: {
|
||||
inputType: 'ObjectConfiguration',
|
||||
returnType: 'ShapePainterObject',
|
||||
},
|
||||
TextEntryObject: {
|
||||
inputType: 'ObjectConfiguration',
|
||||
returnType: 'TextEntryObject',
|
||||
},
|
||||
ParticleEmitterConfiguration: {
|
||||
inputType: 'ObjectConfiguration',
|
||||
returnType: 'ParticleEmitterObject',
|
||||
},
|
||||
CustomObjectConfiguration: {
|
||||
inputType: 'ObjectConfiguration',
|
||||
returnType: 'CustomObjectConfiguration',
|
||||
},
|
||||
Model3DConfiguration: {
|
||||
inputType: 'ObjectConfiguration',
|
||||
returnType: 'Model3DObjectConfiguration',
|
||||
},
|
||||
SpineConfiguration: {
|
||||
inputType: 'ObjectConfiguration',
|
||||
returnType: 'SpineObjectConfiguration',
|
||||
},
|
||||
|
||||
ObjectJsImplementation: { returnType: 'ObjectJsImplementation' },
|
||||
|
||||
ImageResource: { inputType: 'Resource', returnType: 'ImageResource' },
|
||||
};
|
||||
|
||||
const PrimitiveTypes = new Map([
|
||||
['DOMString', 'string'],
|
||||
['long', 'number'],
|
||||
@@ -69,6 +132,8 @@ class Parser {
|
||||
static readUntil(thisCharacter, skipOverIt = true) {
|
||||
let token = '';
|
||||
while (this.currentCharacter !== thisCharacter) {
|
||||
if (this.isDone)
|
||||
throw new Error(`Never reached character '${thisCharacter}'!`);
|
||||
token += this.currentCharacter;
|
||||
this.parserPosition++;
|
||||
}
|
||||
@@ -83,17 +148,23 @@ class Parser {
|
||||
Parser.skipWhitespaces();
|
||||
|
||||
// Read the type
|
||||
let type = Parser.readUntil(' ');
|
||||
/** @type {string} */
|
||||
let type;
|
||||
let optional = false;
|
||||
if (type === 'optional') optional = true;
|
||||
while (type === 'unsigned' || type === 'optional') {
|
||||
// Re-read the type since unsigned is an unnecessary prefix for typescript
|
||||
let attribute = false;
|
||||
do {
|
||||
Parser.skipWhitespaces();
|
||||
type = Parser.readUntil(' ');
|
||||
}
|
||||
if (type === 'optional') optional = true;
|
||||
if (type === 'attribute') attribute = true;
|
||||
} while (
|
||||
type === 'unsigned' ||
|
||||
type === 'optional' ||
|
||||
type === 'attribute'
|
||||
);
|
||||
Parser.skipWhitespaces();
|
||||
|
||||
return { type, optional };
|
||||
return { type, optional, attribute };
|
||||
}
|
||||
|
||||
static readIdentifier() {
|
||||
@@ -137,29 +208,58 @@ for (const [_, enumName, enumCode] of bindingsFile.matchAll(
|
||||
members.push(` ${memberName} = ${i++},`);
|
||||
}
|
||||
enums.push(
|
||||
`enum ${enumName} {
|
||||
`export enum ${enumName} {
|
||||
${members.join('\n')}
|
||||
}`
|
||||
);
|
||||
}
|
||||
|
||||
const interfaces = [];
|
||||
for (const [_, interfaceName, interfaceCode] of bindingsFile.matchAll(
|
||||
/interface\s+([a-zA-Z]+)\s+{\r?\n?([^}]*)\r?\n}/gm
|
||||
const freeFunctions = [];
|
||||
for (const [
|
||||
_,
|
||||
implementationName,
|
||||
interfaceName,
|
||||
interfaceCode,
|
||||
] of bindingsFile.matchAll(
|
||||
/(?:\[JSImplementation=([a-zA-Z0-9]+)\]\r?\n?)?interface\s+([a-zA-Z0-9]+)\s+{(?:}|(?:\r?\n?([^}]*)\r?\n}))/gm
|
||||
)) {
|
||||
if (!interfaceCode) {
|
||||
interfaces.push(
|
||||
`export class ${interfaceName} extends EmscriptenObject {}`
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
const methods = [];
|
||||
const attributes = [];
|
||||
|
||||
Parser.setSource(interfaceCode);
|
||||
while (!Parser.isDone) {
|
||||
const { type: returnType, optional: optionalReturn } = Parser.readType();
|
||||
const {
|
||||
type: returnType,
|
||||
optional: optionalReturn,
|
||||
attribute: isAttribute,
|
||||
} = Parser.readType();
|
||||
|
||||
if (isAttribute) {
|
||||
const attributeName = Parser.readUntil(';');
|
||||
attributes.push(
|
||||
`${attributeName}${optionalReturn ? '?' : ''}: ${returnType};`
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
let methodName = Parser.readUntil('(');
|
||||
const isStatic = methodName.includes('STATIC_');
|
||||
const isFree = methodName.includes('FREE_');
|
||||
const isConstructor = returnType === 'void' && methodName === interfaceName;
|
||||
// Remove prefixes which are not part of the actual function name
|
||||
methodName = methodName
|
||||
.replace('WRAPPED_', '')
|
||||
.replace('MAP_', '')
|
||||
.replace('FREE_', '')
|
||||
.replace('CLONE_', '')
|
||||
.replace('STATIC_', '');
|
||||
// Convert PascalCase to camelCase
|
||||
methodName = methodName[0].toLowerCase() + methodName.slice(1);
|
||||
@@ -195,34 +295,50 @@ for (const [_, interfaceName, interfaceCode] of bindingsFile.matchAll(
|
||||
Parser.parserPosition++;
|
||||
Parser.skipWhitespaces();
|
||||
|
||||
methods.push(
|
||||
`${isStatic ? 'static ' : ''}${
|
||||
isConstructor ? `constructor` : methodName
|
||||
}(${parameters
|
||||
.map(
|
||||
({ name, type, optional, defaultValue }) =>
|
||||
`${name}${optional ? '?' : ''}: ${
|
||||
PrimitiveTypes.has(type) ? PrimitiveTypes.get(type) : type
|
||||
}${defaultValue !== none ? ` = ${defaultValue}` : ''}`
|
||||
)
|
||||
.join(', ')}): ${
|
||||
PrimitiveTypes.has(returnType)
|
||||
? PrimitiveTypes.get(returnType)
|
||||
: returnType
|
||||
};`
|
||||
);
|
||||
const method = `${isStatic ? 'static ' : ''}${
|
||||
isConstructor ? `constructor` : methodName
|
||||
}(${parameters
|
||||
.map(
|
||||
({ name, type, optional, defaultValue }) =>
|
||||
`${name}${optional ? '?' : ''}: ${
|
||||
PrimitiveTypes.has(type) ? PrimitiveTypes.get(type) : type
|
||||
}`
|
||||
)
|
||||
.join(', ')})${
|
||||
isConstructor
|
||||
? ''
|
||||
: `: ${
|
||||
PrimitiveTypes.has(returnType)
|
||||
? PrimitiveTypes.get(returnType)
|
||||
: returnType
|
||||
}`
|
||||
};`;
|
||||
|
||||
if (isFree) freeFunctions.push(`export function ${method}`);
|
||||
methods.push(method);
|
||||
}
|
||||
|
||||
const explicitlyInheritedClass = bindingsFile.match(
|
||||
new RegExp(`(?<![a-zA-Z0-9])${interfaceName} implements ([a-zA-Z0-9]+)`)
|
||||
);
|
||||
const inheritedClass =
|
||||
implementationName ||
|
||||
(!!explicitlyInheritedClass && explicitlyInheritedClass[1]);
|
||||
|
||||
interfaces.push(
|
||||
`export class ${interfaceName} extends EmscriptenObject {
|
||||
${methods.join('\n ')}
|
||||
`export class ${interfaceName} extends ${
|
||||
inheritedClass ? inheritedClass : 'EmscriptenObject'
|
||||
} {${methods.length ? '\n ' + methods.join('\n ') : ''}${
|
||||
attributes.length ? '\n ' + attributes.join('\n ') : ''
|
||||
}
|
||||
}`
|
||||
);
|
||||
}
|
||||
|
||||
const dts = `// Automatically generated by GDevelop.js/scripts/generate-dts.js
|
||||
type float = number;
|
||||
|
||||
class EmscriptenObject {
|
||||
declare class EmscriptenObject {
|
||||
/** The object's index in the WASM memory, and thus its unique identifier. */
|
||||
ptr: number;
|
||||
|
||||
@@ -237,14 +353,91 @@ class EmscriptenObject {
|
||||
* If the object is owned by your code, you should still call this method when adequate, as
|
||||
* otherwise the memory will never be freed, causing a memory leak, which is to be avoided.
|
||||
*/
|
||||
destroy(): void;
|
||||
delete(): void;
|
||||
}
|
||||
|
||||
${enums.join('\n\n')}
|
||||
|
||||
${interfaces.join('\n\n')}
|
||||
|
||||
${freeFunctions.join('\n\n')}
|
||||
${Object.entries(castFunctions)
|
||||
.map(
|
||||
([interfaceName, { returnType, inputType = 'EmscriptenObject' }]) => `
|
||||
export function as${interfaceName}(object: ${inputType}): ${returnType};
|
||||
`
|
||||
)
|
||||
.join('')}
|
||||
|
||||
export const Object: typeof gdObject;
|
||||
|
||||
/**
|
||||
* Initialises the Platforms included in the build (currently, only the JsPlatform),
|
||||
* and loads all built-in extensions into the platform.
|
||||
* To be called once when the library is first loaded.
|
||||
*/
|
||||
export const initializePlatforms: typeof ProjectHelper.initializePlatforms;
|
||||
|
||||
/**
|
||||
* Returns the pointer in WASM memory to an object. It is a number that uniquely
|
||||
* represents that instance of the object.
|
||||
*
|
||||
* @see {@link wrapPointer} to convert a pointer back to an object.
|
||||
*/
|
||||
export function getPointer(object: EmscriptenObject): number;
|
||||
|
||||
type ClassConstructor<T> = {
|
||||
new (...args: any[]): T;
|
||||
};
|
||||
|
||||
/**
|
||||
* Wraps a pointer with a wrapper class, allowing to use the object located at the
|
||||
* pointer's destination as an instance of that class.
|
||||
*
|
||||
* @see {@link getPointer} to get a pointer from an object.
|
||||
*/
|
||||
export function wrapPointer<T extends EmscriptenObject>(ptr: number, objectClass: ClassConstructor<T>): T;
|
||||
|
||||
/**
|
||||
* Casts an object to another class type.
|
||||
*
|
||||
* **Careful** - this is not a conversion function.
|
||||
* This only changes the class type and functions exposed, not the underlying memory.
|
||||
* Only cast to another class if you are certain that the underlying memory is of that type!
|
||||
*/
|
||||
export function castObject<T extends EmscriptenObject>(object: EmscriptenObject, objectClass: ClassConstructor<T>): T;
|
||||
|
||||
/**
|
||||
* Checks whether two objects are pointing to the same underlying memory.
|
||||
* A reference to the object itself is not trustworthy, since there may be multiple
|
||||
* wrapper objects (which allow to call C++ function on C++ memory) for a single
|
||||
* pointer ("real object").
|
||||
*
|
||||
* This function must be therefore used to check for referential equality instead of
|
||||
* JavaScript's standard equality operators when handling Emscripten objects.
|
||||
*/
|
||||
export function compare<T extends EmscriptenObject>(object1: T, object2: T): boolean;
|
||||
|
||||
/**
|
||||
* Call this to free the object's underlying memory. It may not be used afterwards.
|
||||
*
|
||||
* **Call with care** - if the object owns some other objects, those will also be destroyed,
|
||||
* or if this object is owned by another object that does not expect it to be externally deleted
|
||||
* (e.g. it is a child of a map), objects will be put in an invalid state that will most likely
|
||||
* crash the app.
|
||||
*
|
||||
* If the object is owned by your code, you should still call this method when adequate, as
|
||||
* otherwise the memory will never be freed, causing a memory leak, which is to be avoided.
|
||||
*
|
||||
* The alias {@link EmscriptenObject.delete} is recommended instead, for readability.
|
||||
*/
|
||||
export function destroy(object: EmscriptenObject): void;
|
||||
|
||||
export as namespace gd;
|
||||
|
||||
declare global {
|
||||
const gd: typeof gd;
|
||||
}
|
||||
`;
|
||||
|
||||
writeFileSync(__dirname + '/../types.d.ts', dts);
|
||||
|
581
GDevelop.js/types.d.ts
vendored
581
GDevelop.js/types.d.ts
vendored
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
// Automatically generated by GDevelop.js/scripts/generate-types.js
|
||||
declare class gdAbstractFunctionMetadata {
|
||||
addParameter(type: string, description: string, optionalObjectType: string, parameterIsOptional: boolean): gdAbstractFunctionMetadata;
|
||||
addParameter(type: string, description: string, optionalObjectType?: string, parameterIsOptional?: boolean): gdAbstractFunctionMetadata;
|
||||
addCodeOnlyParameter(type: string, supplementaryInformation: string): gdAbstractFunctionMetadata;
|
||||
setDefaultValue(defaultValue: string): gdAbstractFunctionMetadata;
|
||||
setParameterLongDescription(longDescription: string): gdAbstractFunctionMetadata;
|
||||
|
@@ -11,6 +11,8 @@ declare class gdEventsBasedObject extends gdAbstractEventsBasedEntity {
|
||||
getDefaultName(): string;
|
||||
markAsRenderedIn3D(isRenderedIn3D: boolean): gdEventsBasedObject;
|
||||
isRenderedIn3D(): boolean;
|
||||
markAsTextContainer(isTextContainer: boolean): gdEventsBasedObject;
|
||||
isTextContainer(): boolean;
|
||||
static getPropertyActionName(propertyName: string): string;
|
||||
static getPropertyConditionName(propertyName: string): string;
|
||||
static getPropertyExpressionName(propertyName: string): string;
|
||||
|
@@ -15,7 +15,7 @@ function getAtlasTexture(
|
||||
return atlasTextures[tilesetId];
|
||||
}
|
||||
|
||||
let texture = null;
|
||||
let texture: Texture | null = null;
|
||||
|
||||
const tileset = tilesetCache[tilesetId];
|
||||
if (tileset?.relPath) {
|
||||
|
@@ -21,11 +21,6 @@
|
||||
# JSS triggers a Flow error
|
||||
<PROJECT_ROOT>/node_modules/jss/src/index.js
|
||||
|
||||
[include]
|
||||
# Type check the declarations of the JavaScript extensions (i.e: JsExtension.js files) with Flow
|
||||
# (and actually any file in Extensions containing `// @flow`).
|
||||
../../Extensions
|
||||
|
||||
[libs]
|
||||
../../GDevelop.js/types
|
||||
|
||||
|
BIN
newIDE/app/public/res/actions/filletRectangle.png
Normal file
BIN
newIDE/app/public/res/actions/filletRectangle.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 731 B |
BIN
newIDE/app/public/res/actions/filletRectangle24.png
Normal file
BIN
newIDE/app/public/res/actions/filletRectangle24.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 848 B |
@@ -341,8 +341,9 @@
|
||||
"description": {
|
||||
"messageByLocale": {
|
||||
"en": "Let's choose an **object** from the asset store",
|
||||
"fr": "Nous allons choisir un objet dans le **magasin de ressources**.",
|
||||
"fr": "Nous allons choisir un **objet** dans le magasin de ressources.",
|
||||
"es": "Vamos a elegir un **objeto** de la tienda de recursos.",
|
||||
"pt": "Vamos escolher um objeto da loja de recursos.",
|
||||
"th": "เลือก **วัตถุ** จาก ร้านค้า asset",
|
||||
"ar": "هيّا نقوم باختيار **كائن** من متجر العناصر"
|
||||
}
|
||||
@@ -2180,6 +2181,7 @@
|
||||
"en": "Add a few $(obstacle) to the **scene** to protect $(target).",
|
||||
"fr": "Ajoutez quelques $(obstacle) à la **scène** pour protéger $(target).",
|
||||
"es": "Agrega algunos $(obstacle) a la **escena** para proteger a $(target).",
|
||||
"pt": "Adicione alguns $(obstacle) à **cena** para proteger $(target).",
|
||||
"th": "เพิ่ม $(obstacle) ปริมาณนิดหน่อยลงใน **scene** เพื่อป้องกัน $(target)",
|
||||
"ar": "إضافة بضعة $(obstacle) إلى **المشهد** لحماية $(target)."
|
||||
}
|
||||
|
@@ -2,7 +2,24 @@
|
||||
{
|
||||
"id": "cameraParallax",
|
||||
"contentUrl": "https://resources.gdevelop-app.com/in-app-tutorials/cameraParallax.json",
|
||||
"availableLocales": ["en", "fr", "es", "pt", "th", "ar"],
|
||||
"availableLocales": [
|
||||
"en",
|
||||
"fr",
|
||||
"ar",
|
||||
"de",
|
||||
"es",
|
||||
"it",
|
||||
"ja",
|
||||
"ko",
|
||||
"pl",
|
||||
"pt",
|
||||
"th",
|
||||
"ru",
|
||||
"sl",
|
||||
"sq",
|
||||
"uk",
|
||||
"zh"
|
||||
],
|
||||
"initialTemplateUrl": "https://resources.gdevelop-app.com/in-app-tutorials/templates/cameraParallax/game.json",
|
||||
"initialProjectData": {
|
||||
"cameraScene": "CameraScene",
|
||||
@@ -19,14 +36,48 @@
|
||||
{
|
||||
"id": "healthBar",
|
||||
"contentUrl": "https://resources.gdevelop-app.com/in-app-tutorials/healthBar.json",
|
||||
"availableLocales": ["en", "fr", "es", "pt", "th", "ar"],
|
||||
"availableLocales": [
|
||||
"en",
|
||||
"fr",
|
||||
"ar",
|
||||
"de",
|
||||
"es",
|
||||
"it",
|
||||
"ja",
|
||||
"ko",
|
||||
"pl",
|
||||
"pt",
|
||||
"th",
|
||||
"ru",
|
||||
"sl",
|
||||
"sq",
|
||||
"uk",
|
||||
"zh"
|
||||
],
|
||||
"initialTemplateUrl": "https://resources.gdevelop-app.com/in-app-tutorials/templates/healthBar/game.json",
|
||||
"initialProjectData": { "level": "Level", "player": "Player" }
|
||||
},
|
||||
{
|
||||
"id": "joystick",
|
||||
"contentUrl": "https://resources.gdevelop-app.com/in-app-tutorials/joystick.json",
|
||||
"availableLocales": ["en", "fr", "es", "pt", "th", "ar", "sq"],
|
||||
"availableLocales": [
|
||||
"en",
|
||||
"fr",
|
||||
"ar",
|
||||
"de",
|
||||
"es",
|
||||
"it",
|
||||
"ja",
|
||||
"ko",
|
||||
"pl",
|
||||
"pt",
|
||||
"th",
|
||||
"ru",
|
||||
"sl",
|
||||
"sq",
|
||||
"uk",
|
||||
"zh"
|
||||
],
|
||||
"initialTemplateUrl": "https://resources.gdevelop-app.com/in-app-tutorials/templates/joystick/game.json",
|
||||
"initialProjectData": {
|
||||
"gameScene": "GameScene",
|
||||
@@ -36,14 +87,48 @@
|
||||
{
|
||||
"id": "object3d",
|
||||
"contentUrl": "https://resources.gdevelop-app.com/in-app-tutorials/object3d.json",
|
||||
"availableLocales": ["en", "fr", "es", "pt", "th", "ar"],
|
||||
"availableLocales": [
|
||||
"en",
|
||||
"fr",
|
||||
"ar",
|
||||
"de",
|
||||
"es",
|
||||
"it",
|
||||
"ja",
|
||||
"ko",
|
||||
"pl",
|
||||
"pt",
|
||||
"th",
|
||||
"ru",
|
||||
"sl",
|
||||
"sq",
|
||||
"uk",
|
||||
"zh"
|
||||
],
|
||||
"initialTemplateUrl": "https://resources.gdevelop-app.com/in-app-tutorials/templates/object3d/game.json",
|
||||
"initialProjectData": { "gameScene": "GameScene" }
|
||||
"initialProjectData": { "gameScene": "GameScene", "platform": "Platform" }
|
||||
},
|
||||
{
|
||||
"id": "plinkoMultiplier",
|
||||
"contentUrl": "https://resources.gdevelop-app.com/in-app-tutorials/plinkoMultiplier.json",
|
||||
"availableLocales": ["en", "fr", "es", "pt", "th", "ar"],
|
||||
"availableLocales": [
|
||||
"en",
|
||||
"fr",
|
||||
"ar",
|
||||
"de",
|
||||
"es",
|
||||
"it",
|
||||
"ja",
|
||||
"ko",
|
||||
"pl",
|
||||
"pt",
|
||||
"th",
|
||||
"ru",
|
||||
"sl",
|
||||
"sq",
|
||||
"uk",
|
||||
"zh"
|
||||
],
|
||||
"initialTemplateUrl": "https://resources.gdevelop-app.com/in-app-tutorials/templates/plinkoMultiplier/game.json",
|
||||
"initialProjectData": {
|
||||
"gameScene": "GameScene",
|
||||
@@ -56,7 +141,24 @@
|
||||
{
|
||||
"id": "timer",
|
||||
"contentUrl": "https://resources.gdevelop-app.com/in-app-tutorials/timer.json",
|
||||
"availableLocales": ["en", "fr", "es", "pt", "th", "ar"],
|
||||
"availableLocales": [
|
||||
"en",
|
||||
"fr",
|
||||
"ar",
|
||||
"de",
|
||||
"es",
|
||||
"it",
|
||||
"ja",
|
||||
"ko",
|
||||
"pl",
|
||||
"pt",
|
||||
"th",
|
||||
"ru",
|
||||
"sl",
|
||||
"sq",
|
||||
"uk",
|
||||
"zh"
|
||||
],
|
||||
"initialTemplateUrl": "https://resources.gdevelop-app.com/in-app-tutorials/templates/timer/game.json",
|
||||
"initialProjectData": { "gameScene": "GameScene" }
|
||||
}
|
||||
|
@@ -61,6 +61,13 @@ if (!args['examplesGitPath']) {
|
||||
}
|
||||
const examplesGitPath = args['examplesGitPath'];
|
||||
|
||||
if (!args['templatesGitPath']) {
|
||||
shell.echo(
|
||||
'⚠️ You should pass --templatesGitPath pointing to the git directory of GDevelop-game-templates.'
|
||||
);
|
||||
}
|
||||
const templatesGitPath = args['templatesGitPath'];
|
||||
|
||||
/** @typedef {{sha: string, message: string, authorEmail: string}} GitRawCommitInfo */
|
||||
/** @typedef {{
|
||||
message: string,
|
||||
@@ -321,6 +328,7 @@ const formatHiddenCommitMessage = commit => {
|
||||
* extensionsCommits: GitEnrichedCommitInfo[] | null,
|
||||
* assetsCommits: GitEnrichedCommitInfo[] | null,
|
||||
* examplesCommits: GitEnrichedCommitInfo[] | null,
|
||||
* templatesCommits: GitEnrichedCommitInfo[] | null
|
||||
* }} commits
|
||||
*/
|
||||
const outputChangelog = ({
|
||||
@@ -331,6 +339,7 @@ const outputChangelog = ({
|
||||
extensionsCommits,
|
||||
assetsCommits,
|
||||
examplesCommits,
|
||||
templatesCommits,
|
||||
}) => {
|
||||
shell.echo(
|
||||
`ℹ️ Hidden these commits: \n${hiddenCommits
|
||||
@@ -378,6 +387,14 @@ const outputChangelog = ({
|
||||
.join('\n')
|
||||
: 'TODO: Add examples commits here.'
|
||||
);
|
||||
shell.echo('\n## 🕹 Premium Game Templates\n');
|
||||
shell.echo(
|
||||
templatesCommits
|
||||
? templatesCommits
|
||||
.map(commit => formatCommitMessage({ commit, includeAuthor: false }))
|
||||
.join('\n')
|
||||
: 'TODO: Add game templates commits here.'
|
||||
);
|
||||
|
||||
if (devCommits.length > 0) {
|
||||
shell.echo(`\n### 🛠 Internal changes (for developers)\n`);
|
||||
@@ -446,6 +463,17 @@ const outputChangelog = ({
|
||||
);
|
||||
}
|
||||
|
||||
let templatesCommits = null;
|
||||
if (templatesGitPath) {
|
||||
const templatesRepoGitTools = getGitTools(templatesGitPath);
|
||||
const templatesRawCommits = templatesRepoGitTools.extractCommitsSinceDate(
|
||||
lastTagDate
|
||||
);
|
||||
templatesCommits = enrichCommits(templatesRawCommits).filter(
|
||||
commit => !commit.hidden
|
||||
);
|
||||
}
|
||||
|
||||
outputChangelog({
|
||||
hiddenCommits,
|
||||
improvementsCommits,
|
||||
@@ -454,5 +482,6 @@ const outputChangelog = ({
|
||||
extensionsCommits,
|
||||
assetsCommits,
|
||||
examplesCommits,
|
||||
templatesCommits,
|
||||
});
|
||||
})();
|
||||
|
@@ -26,6 +26,8 @@ import {
|
||||
PrivateGameTemplateTile,
|
||||
} from './ShopTiles';
|
||||
import { useDebounce } from '../Utils/UseDebounce';
|
||||
import PromotionsSlideshow from '../Promotions/PromotionsSlideshow';
|
||||
import { ColumnStackLayout } from '../UI/Layout';
|
||||
|
||||
const cellSpacing = 2;
|
||||
|
||||
@@ -157,6 +159,7 @@ type Props = {|
|
||||
onCategorySelection: string => void,
|
||||
openedShopCategory: string | null,
|
||||
hideGameTemplates?: boolean,
|
||||
displayPromotions?: boolean,
|
||||
|};
|
||||
|
||||
export const AssetsHome = React.forwardRef<Props, AssetsHomeInterface>(
|
||||
@@ -171,6 +174,7 @@ export const AssetsHome = React.forwardRef<Props, AssetsHomeInterface>(
|
||||
onCategorySelection,
|
||||
openedShopCategory,
|
||||
hideGameTemplates,
|
||||
displayPromotions,
|
||||
}: Props,
|
||||
ref
|
||||
) => {
|
||||
@@ -383,6 +387,15 @@ export const AssetsHome = React.forwardRef<Props, AssetsHomeInterface>(
|
||||
</GridList>
|
||||
</>
|
||||
)}
|
||||
{displayPromotions ? (
|
||||
<ColumnStackLayout>
|
||||
<Text size="block-title">
|
||||
<Trans>Promotions</Trans>
|
||||
</Text>
|
||||
|
||||
<PromotionsSlideshow />
|
||||
</ColumnStackLayout>
|
||||
) : null}
|
||||
{allBundleTiles.length ? (
|
||||
<>
|
||||
<Column>
|
||||
|
@@ -17,7 +17,9 @@ export type ExampleStoreDialogProps = {|
|
||||
onSelectPrivateGameTemplateListingData: (
|
||||
privateGameTemplateListingData: ?PrivateGameTemplateListingData
|
||||
) => void,
|
||||
onOpenNewProjectSetupDialog: () => void,
|
||||
onOpenNewProjectSetupDialog: (
|
||||
initialTab: 'from-scratch' | 'ai' | 'example'
|
||||
) => void,
|
||||
isProjectOpening: boolean,
|
||||
|};
|
||||
|
||||
@@ -44,7 +46,7 @@ const ExampleStoreDialog = ({
|
||||
id="create-blank-project-button"
|
||||
label={<Trans>Create a blank project</Trans>}
|
||||
primary
|
||||
onClick={onOpenNewProjectSetupDialog}
|
||||
onClick={() => onOpenNewProjectSetupDialog('from-scratch')}
|
||||
/>,
|
||||
],
|
||||
[onClose, onOpenNewProjectSetupDialog]
|
||||
@@ -59,7 +61,7 @@ const ExampleStoreDialog = ({
|
||||
title={<Trans>Create a new project</Trans>}
|
||||
actions={actions}
|
||||
onRequestClose={onClose}
|
||||
onApply={onOpenNewProjectSetupDialog}
|
||||
onApply={() => onOpenNewProjectSetupDialog('from-scratch')}
|
||||
open={open}
|
||||
fullHeight
|
||||
flexColumnBody
|
||||
@@ -67,7 +69,9 @@ const ExampleStoreDialog = ({
|
||||
<ExampleStore
|
||||
focusOnMount
|
||||
isOpening={isProjectOpening}
|
||||
onOpenNewProjectSetupDialog={onOpenNewProjectSetupDialog}
|
||||
onOpenNewProjectSetupDialog={() =>
|
||||
onOpenNewProjectSetupDialog('example')
|
||||
}
|
||||
onSelectExampleShortHeader={onSelectExampleShortHeader}
|
||||
onSelectPrivateGameTemplateListingData={
|
||||
onSelectPrivateGameTemplateListingData
|
||||
|
@@ -93,7 +93,6 @@ export const CustomObjectPackResults = ({
|
||||
<TextButton
|
||||
icon={<ChevronArrowLeft />}
|
||||
label={<Trans>Back</Trans>}
|
||||
primary={false}
|
||||
onClick={onBack}
|
||||
disabled={isAssetBeingInstalled}
|
||||
/>
|
||||
|
@@ -59,6 +59,7 @@ import { PrivateGameTemplateStoreContext } from './PrivateGameTemplates/PrivateG
|
||||
|
||||
type Props = {|
|
||||
hideGameTemplates?: boolean, // TODO: if we add more options, use an array instead.
|
||||
displayPromotions?: boolean,
|
||||
onOpenPrivateGameTemplateListingData?: (
|
||||
privateGameTemplateListingData: PrivateGameTemplateListingData
|
||||
) => void,
|
||||
@@ -94,7 +95,14 @@ const identifyAssetPackKind = ({
|
||||
};
|
||||
|
||||
export const AssetStore = React.forwardRef<Props, AssetStoreInterface>(
|
||||
({ hideGameTemplates, onOpenPrivateGameTemplateListingData }: Props, ref) => {
|
||||
(
|
||||
{
|
||||
hideGameTemplates,
|
||||
displayPromotions,
|
||||
onOpenPrivateGameTemplateListingData,
|
||||
}: Props,
|
||||
ref
|
||||
) => {
|
||||
const {
|
||||
assetShortHeadersSearchResults,
|
||||
publicAssetPacksSearchResults,
|
||||
@@ -652,7 +660,6 @@ export const AssetStore = React.forwardRef<Props, AssetStoreInterface>(
|
||||
<TextButton
|
||||
icon={<ChevronArrowLeft />}
|
||||
label={<Trans>Back</Trans>}
|
||||
primary={false}
|
||||
onClick={async () => {
|
||||
const page = shopNavigationState.backToPreviousPage();
|
||||
const isUpdatingSearchtext = reApplySearchTextIfNeeded(
|
||||
@@ -738,6 +745,7 @@ export const AssetStore = React.forwardRef<Props, AssetStoreInterface>(
|
||||
onCategorySelection={selectShopCategory}
|
||||
openedShopCategory={openedShopCategory}
|
||||
hideGameTemplates={hideGameTemplates}
|
||||
displayPromotions={displayPromotions}
|
||||
/>
|
||||
) : (
|
||||
<PlaceholderLoader />
|
||||
|
@@ -43,6 +43,7 @@ import useAlertDialog from '../UI/Alert/useAlertDialog';
|
||||
import PasteIcon from '../UI/CustomSvgIcons/Clipboard';
|
||||
import CopyIcon from '../UI/CustomSvgIcons/Copy';
|
||||
import ResponsiveFlatButton from '../UI/ResponsiveFlatButton';
|
||||
import { useResponsiveWindowSize } from '../UI/Responsive/ResponsiveWindowMeasurer';
|
||||
|
||||
const gd: libGDevelop = global.gd;
|
||||
|
||||
@@ -281,6 +282,7 @@ type Props = {|
|
||||
|};
|
||||
|
||||
const BehaviorsEditor = (props: Props) => {
|
||||
const { isMobile } = useResponsiveWindowSize();
|
||||
const scrollView = React.useRef<?ScrollViewInterface>(null);
|
||||
const [
|
||||
justAddedBehaviorName,
|
||||
@@ -598,7 +600,9 @@ const BehaviorsEditor = (props: Props) => {
|
||||
helpPagePath="/behaviors"
|
||||
tutorialId="intro-behaviors-and-functions"
|
||||
actionButtonId="add-behavior-button"
|
||||
actionLabel={<Trans>Add a behavior</Trans>}
|
||||
actionLabel={
|
||||
isMobile ? <Trans>Add</Trans> : <Trans>Add a behavior</Trans>
|
||||
}
|
||||
onAction={() => setNewBehaviorDialogOpen(true)}
|
||||
secondaryActionIcon={<PasteIcon />}
|
||||
secondaryActionLabel={
|
||||
@@ -645,7 +649,13 @@ const BehaviorsEditor = (props: Props) => {
|
||||
<ResponsiveFlatButton
|
||||
key={'copy-all-behaviors'}
|
||||
leftIcon={<CopyIcon />}
|
||||
label={<Trans>Copy all behaviors</Trans>}
|
||||
label={
|
||||
isMobile ? (
|
||||
<Trans>Copy all</Trans>
|
||||
) : (
|
||||
<Trans>Copy all behaviors</Trans>
|
||||
)
|
||||
}
|
||||
onClick={() => {
|
||||
copyAllBehaviors();
|
||||
}}
|
||||
@@ -663,7 +673,13 @@ const BehaviorsEditor = (props: Props) => {
|
||||
<LineStackLayout justifyContent="flex-end" expand>
|
||||
<RaisedButton
|
||||
key="add-behavior-line"
|
||||
label={<Trans>Add a behavior</Trans>}
|
||||
label={
|
||||
isMobile ? (
|
||||
<Trans>Add</Trans>
|
||||
) : (
|
||||
<Trans>Add a behavior</Trans>
|
||||
)
|
||||
}
|
||||
primary
|
||||
onClick={() => setNewBehaviorDialogOpen(true)}
|
||||
icon={<Add />}
|
||||
|
@@ -106,6 +106,14 @@ export default function EventsBasedObjectEditor({
|
||||
onChange();
|
||||
}}
|
||||
/>
|
||||
<Checkbox
|
||||
label={<Trans>Contains text</Trans>}
|
||||
checked={eventsBasedObject.isTextContainer()}
|
||||
onCheck={(e, checked) => {
|
||||
eventsBasedObject.markAsTextContainer(checked);
|
||||
onChange();
|
||||
}}
|
||||
/>
|
||||
{eventsBasedObject.getEventsFunctions().getEventsFunctionsCount() ===
|
||||
0 && (
|
||||
<DismissableAlertMessage
|
||||
|
@@ -370,7 +370,6 @@ const PublishHome = ({
|
||||
<TextButton
|
||||
icon={<ChevronArrowLeft />}
|
||||
label={<Trans>Back</Trans>}
|
||||
primary={false}
|
||||
onClick={onBack}
|
||||
disabled={isNavigationDisabled}
|
||||
/>
|
||||
|
@@ -1039,20 +1039,20 @@ const InAppTutorialOrchestrator = React.forwardRef<
|
||||
|
||||
let formattedStepTrigger;
|
||||
const stepTrigger = currentStep.nextStepTrigger;
|
||||
if (stepTrigger) {
|
||||
if (stepTrigger.clickOnTooltipButton) {
|
||||
const formattedButtonLabel = translateAndInterpolateText({
|
||||
text: stepTrigger.clickOnTooltipButton,
|
||||
data,
|
||||
i18n,
|
||||
project,
|
||||
});
|
||||
formattedStepTrigger = formattedButtonLabel
|
||||
? {
|
||||
clickOnTooltipButton: formattedButtonLabel,
|
||||
}
|
||||
: undefined;
|
||||
}
|
||||
if (stepTrigger && stepTrigger.clickOnTooltipButton) {
|
||||
const formattedButtonLabel = translateAndInterpolateText({
|
||||
text: stepTrigger.clickOnTooltipButton,
|
||||
data,
|
||||
i18n,
|
||||
project,
|
||||
});
|
||||
formattedStepTrigger = formattedButtonLabel
|
||||
? {
|
||||
clickOnTooltipButton: formattedButtonLabel,
|
||||
}
|
||||
: undefined;
|
||||
} else {
|
||||
formattedStepTrigger = stepTrigger;
|
||||
}
|
||||
const formattedStep: InAppTutorialFlowFormattedStep = {
|
||||
...currentStep,
|
||||
|
@@ -100,7 +100,10 @@ const getWrongEditorTooltip = (
|
||||
|
||||
export const queryElementOrItsMostVisuallySignificantParent = (
|
||||
elementToHighlightId: string
|
||||
) => {
|
||||
): {|
|
||||
elementToHighlight: ?HTMLElement,
|
||||
elementWithId: ?HTMLElement,
|
||||
|} => {
|
||||
let foundElement = document.querySelector(elementToHighlightId);
|
||||
if (foundElement instanceof HTMLTextAreaElement) {
|
||||
// In this case, the element to highlight is a Material UI multiline text field
|
||||
@@ -108,7 +111,7 @@ export const queryElementOrItsMostVisuallySignificantParent = (
|
||||
// to highlight the parent div.
|
||||
const parentDiv = foundElement.closest('div');
|
||||
if (parentDiv instanceof HTMLElement && isElementAMuiInput(parentDiv)) {
|
||||
foundElement = parentDiv;
|
||||
return { elementToHighlight: parentDiv, elementWithId: foundElement };
|
||||
}
|
||||
} else if (
|
||||
foundElement instanceof HTMLInputElement &&
|
||||
@@ -116,10 +119,13 @@ export const queryElementOrItsMostVisuallySignificantParent = (
|
||||
) {
|
||||
const containerDiv = foundElement.closest('div[data-search-bar-container]');
|
||||
if (containerDiv instanceof HTMLElement) {
|
||||
foundElement = containerDiv;
|
||||
return { elementToHighlight: containerDiv, elementWithId: foundElement };
|
||||
}
|
||||
}
|
||||
return foundElement;
|
||||
return {
|
||||
elementToHighlight: foundElement,
|
||||
elementWithId: foundElement,
|
||||
};
|
||||
};
|
||||
|
||||
type Props = {|
|
||||
@@ -149,6 +155,7 @@ function InAppTutorialStepDisplayer({
|
||||
elementToHighlight,
|
||||
setElementToHighlight,
|
||||
] = React.useState<?HTMLElement>(null);
|
||||
const [elementWithId, setElementWithId] = React.useState<?HTMLElement>(null);
|
||||
const [
|
||||
hideBehindOtherDialog,
|
||||
setHideBehindOtherDialog,
|
||||
@@ -169,9 +176,12 @@ function InAppTutorialStepDisplayer({
|
||||
() => {
|
||||
if (!elementToHighlightId) return;
|
||||
|
||||
setElementToHighlight(
|
||||
queryElementOrItsMostVisuallySignificantParent(elementToHighlightId)
|
||||
);
|
||||
const {
|
||||
elementToHighlight,
|
||||
elementWithId,
|
||||
} = queryElementOrItsMostVisuallySignificantParent(elementToHighlightId);
|
||||
setElementToHighlight(elementToHighlight);
|
||||
setElementWithId(elementWithId);
|
||||
},
|
||||
[elementToHighlightId]
|
||||
);
|
||||
@@ -262,6 +272,36 @@ function InAppTutorialStepDisplayer({
|
||||
);
|
||||
};
|
||||
|
||||
const getFillAutomaticallyFunction = React.useCallback(
|
||||
() => {
|
||||
if (!nextStepTrigger || !nextStepTrigger.valueEquals) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (
|
||||
!(elementWithId instanceof HTMLInputElement) &&
|
||||
!(elementWithId instanceof HTMLTextAreaElement)
|
||||
) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const valuePropertyDescriptor = Object.getOwnPropertyDescriptor(
|
||||
elementWithId.constructor.prototype,
|
||||
'value'
|
||||
);
|
||||
if (!valuePropertyDescriptor) return undefined;
|
||||
const valueSetter = valuePropertyDescriptor.set;
|
||||
if (!valueSetter) return undefined;
|
||||
return () => {
|
||||
valueSetter.call(elementWithId, nextStepTrigger.valueEquals);
|
||||
// Trigger blur to make sure the value is taken into account
|
||||
// by the React input.
|
||||
elementWithId.dispatchEvent(new Event('blur', { bubbles: true }));
|
||||
};
|
||||
},
|
||||
[nextStepTrigger, elementWithId]
|
||||
);
|
||||
|
||||
const renderTooltip = (i18n: I18nType) => {
|
||||
if (tooltip && !expectedEditor) {
|
||||
const anchorElement = tooltip.standalone
|
||||
@@ -281,6 +321,7 @@ function InAppTutorialStepDisplayer({
|
||||
? nextStepTrigger.clickOnTooltipButton
|
||||
: undefined
|
||||
}
|
||||
fillAutomatically={getFillAutomaticallyFunction()}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -290,7 +331,7 @@ function InAppTutorialStepDisplayer({
|
||||
return (
|
||||
<InAppTutorialTooltipDisplayer
|
||||
endTutorial={endTutorial}
|
||||
showQuitButton={!isOnClosableDialog}
|
||||
showQuitButton // Always show the quit button when the user is on the wrong editor
|
||||
anchorElement={assistantImage}
|
||||
tooltip={wrongEditorTooltip}
|
||||
progress={progress}
|
||||
|
@@ -21,6 +21,7 @@ import { LineStackLayout } from '../UI/Layout';
|
||||
import ChevronArrowTop from '../UI/CustomSvgIcons/ChevronArrowTop';
|
||||
import { textEllipsisStyle } from '../UI/TextEllipsis';
|
||||
import { useResponsiveWindowSize } from '../UI/Responsive/ResponsiveWindowMeasurer';
|
||||
import TextButton from '../UI/TextButton';
|
||||
|
||||
const themeColors = {
|
||||
grey10: '#EBEBED',
|
||||
@@ -129,12 +130,14 @@ type TooltipBodyProps = {|
|
||||
tooltip: InAppTutorialFormattedTooltip,
|
||||
buttonLabel?: string,
|
||||
goToNextStep: () => void,
|
||||
fillAutomatically?: () => void,
|
||||
|};
|
||||
|
||||
const TooltipBody = ({
|
||||
tooltip,
|
||||
buttonLabel,
|
||||
goToNextStep,
|
||||
fillAutomatically,
|
||||
}: TooltipBodyProps) => {
|
||||
const { isMobile } = useResponsiveWindowSize();
|
||||
const titleAndDescription = (
|
||||
@@ -182,10 +185,18 @@ const TooltipBody = ({
|
||||
</Column>
|
||||
);
|
||||
|
||||
const fillAutomaticallyButton = fillAutomatically && (
|
||||
<TextButton
|
||||
onClick={fillAutomatically}
|
||||
label={<Trans>Fill automatically</Trans>}
|
||||
primary
|
||||
/>
|
||||
);
|
||||
return (
|
||||
<Column noMargin>
|
||||
{titleAndDescription}
|
||||
{imageAndButton}
|
||||
{fillAutomaticallyButton}
|
||||
</Column>
|
||||
);
|
||||
};
|
||||
@@ -287,6 +298,7 @@ type Props = {|
|
||||
progress: number,
|
||||
endTutorial: () => void,
|
||||
goToNextStep: () => void,
|
||||
fillAutomatically?: () => void,
|
||||
|};
|
||||
|
||||
const InAppTutorialTooltipDisplayer = ({
|
||||
@@ -297,6 +309,7 @@ const InAppTutorialTooltipDisplayer = ({
|
||||
progress,
|
||||
endTutorial,
|
||||
goToNextStep,
|
||||
fillAutomatically,
|
||||
}: Props) => {
|
||||
const { isMobile } = useResponsiveWindowSize();
|
||||
const {
|
||||
@@ -388,6 +401,7 @@ const InAppTutorialTooltipDisplayer = ({
|
||||
tooltip={tooltip}
|
||||
buttonLabel={buttonLabel}
|
||||
goToNextStep={goToNextStep}
|
||||
fillAutomatically={fillAutomatically}
|
||||
/>
|
||||
)}
|
||||
</Column>
|
||||
|
@@ -98,7 +98,9 @@ export type RenderEditorContainerProps = {|
|
||||
canInstallPrivateAsset: () => boolean,
|
||||
|
||||
// Project creation
|
||||
onOpenNewProjectSetupDialog: () => void,
|
||||
onOpenNewProjectSetupDialog: (
|
||||
initialTab: 'from-scratch' | 'ai' | 'example'
|
||||
) => void,
|
||||
|
||||
// Project save
|
||||
onSave: () => Promise<void>,
|
||||
|
@@ -63,6 +63,7 @@ import ContextMenu, {
|
||||
type ContextMenuInterface,
|
||||
} from '../../../../UI/Menu/ContextMenu';
|
||||
import type { ClientCoordinates } from '../../../../Utils/UseLongTouch';
|
||||
import PromotionsSlideshow from '../../../../Promotions/PromotionsSlideshow';
|
||||
const electron = optionalRequire('electron');
|
||||
const path = optionalRequire('path');
|
||||
|
||||
@@ -107,7 +108,7 @@ type Props = {|
|
||||
canOpen: boolean,
|
||||
onChooseProject: () => void,
|
||||
onOpenRecentFile: (file: FileMetadataAndStorageProviderName) => Promise<void>,
|
||||
onOpenNewProjectSetupDialog: () => void,
|
||||
onOpenNewProjectSetupDialog: (initialTab: 'ai' | 'from-scratch') => void,
|
||||
onSelectExampleShortHeader: (exampleShortHeader: ExampleShortHeader) => void,
|
||||
onSelectPrivateGameTemplateListingData: (
|
||||
privateGameTemplateListingData: PrivateGameTemplateListingData
|
||||
@@ -178,6 +179,8 @@ const BuildSection = ({
|
||||
setLastModifiedInfoByProjectId,
|
||||
] = React.useState({});
|
||||
|
||||
const isMediumOrSmallScreen =
|
||||
windowSize === 'small' || windowSize === 'medium';
|
||||
const columnsCount = getItemsColumns(windowSize, isLandscape);
|
||||
|
||||
const allGameTemplatesAndExamplesFlaggedAsGameCount = React.useMemo(
|
||||
@@ -419,7 +422,7 @@ const BuildSection = ({
|
||||
) : (
|
||||
<SectionContainer
|
||||
title={<Trans>My projects</Trans>}
|
||||
showAnnouncementsAndPromotions
|
||||
showUrgentAnnouncements
|
||||
renderFooter={
|
||||
limits && hasTooManyCloudProjects
|
||||
? () => (
|
||||
@@ -452,6 +455,10 @@ const BuildSection = ({
|
||||
roundedImages
|
||||
displayArrowsOnDesktop
|
||||
/>
|
||||
<Spacer />
|
||||
<Column noMargin>
|
||||
<PromotionsSlideshow />
|
||||
</Column>
|
||||
</SectionRow>
|
||||
<SectionRow>
|
||||
<ResponsiveLineStackLayout
|
||||
@@ -483,34 +490,41 @@ const BuildSection = ({
|
||||
primary
|
||||
fullWidth={!canOpen}
|
||||
label={
|
||||
isMobile ? (
|
||||
isMediumOrSmallScreen ? (
|
||||
<Trans>Create</Trans>
|
||||
) : (
|
||||
<Trans>Create a project</Trans>
|
||||
)
|
||||
}
|
||||
onClick={onOpenNewProjectSetupDialog}
|
||||
onClick={() => onOpenNewProjectSetupDialog('from-scratch')}
|
||||
icon={<Add fontSize="small" />}
|
||||
id="home-create-project-button"
|
||||
/>
|
||||
<RaisedButton
|
||||
primary
|
||||
fullWidth={!canOpen}
|
||||
label={
|
||||
isMediumOrSmallScreen ? (
|
||||
<Trans>✨ AI prototype</Trans>
|
||||
) : (
|
||||
<Trans>✨ Prototype with AI</Trans>
|
||||
)
|
||||
}
|
||||
onClick={() => onOpenNewProjectSetupDialog('ai')}
|
||||
id="home-create-project-button"
|
||||
/>
|
||||
{canOpen && (
|
||||
<>
|
||||
<Text>
|
||||
<Trans>or</Trans>
|
||||
</Text>
|
||||
<Spacer />
|
||||
<TextButton
|
||||
primary
|
||||
label={
|
||||
isMobile ? (
|
||||
<Trans>Open</Trans>
|
||||
) : (
|
||||
<Trans>Open a project</Trans>
|
||||
)
|
||||
}
|
||||
onClick={onChooseProject}
|
||||
/>
|
||||
</>
|
||||
<TextButton
|
||||
secondary
|
||||
label={
|
||||
isMediumOrSmallScreen ? (
|
||||
<Trans>Import</Trans>
|
||||
) : (
|
||||
<Trans>Import a project</Trans>
|
||||
)
|
||||
}
|
||||
onClick={onChooseProject}
|
||||
/>
|
||||
)}
|
||||
</LineStackLayout>
|
||||
</Column>
|
||||
|
@@ -17,6 +17,7 @@ import List from '@material-ui/core/List';
|
||||
import ErrorBoundary from '../../../UI/ErrorBoundary';
|
||||
import { AnnouncementsFeed } from '../../../AnnouncementsFeed';
|
||||
import { AnnouncementsFeedContext } from '../../../AnnouncementsFeed/AnnouncementsFeedContext';
|
||||
import PromotionsSlideshow from '../../../Promotions/PromotionsSlideshow';
|
||||
|
||||
const styles = {
|
||||
list: {
|
||||
@@ -71,10 +72,7 @@ const CommunitySection = () => {
|
||||
announcements && announcements.length > 0;
|
||||
|
||||
return (
|
||||
<SectionContainer
|
||||
title={<Trans>Community</Trans>}
|
||||
showAnnouncementsAndPromotions
|
||||
>
|
||||
<SectionContainer title={<Trans>Community</Trans>} showUrgentAnnouncements>
|
||||
<SectionRow>
|
||||
<ColumnStackLayout noMargin expand>
|
||||
{shouldDisplayAnnouncementsTitle && (
|
||||
@@ -82,6 +80,7 @@ const CommunitySection = () => {
|
||||
<Trans>News and announcements</Trans>
|
||||
</Text>
|
||||
)}
|
||||
<PromotionsSlideshow />
|
||||
<AnnouncementsFeed canClose={false} level="normal" />
|
||||
<Text size="title">
|
||||
<Trans>Join the conversation</Trans>
|
||||
|
@@ -18,7 +18,7 @@ import {
|
||||
type WindowSizeType,
|
||||
} from '../../../../UI/Responsive/ResponsiveWindowMeasurer';
|
||||
import Text from '../../../../UI/Text';
|
||||
import { Column } from '../../../../UI/Grid';
|
||||
import { Column, Spacer } from '../../../../UI/Grid';
|
||||
import { type Tutorial } from '../../../../Utils/GDevelopServices/Tutorial';
|
||||
import { type SubscriptionPlanWithPricingSystems } from '../../../../Utils/GDevelopServices/Usage';
|
||||
import { CardWidget } from '../CardWidget';
|
||||
@@ -32,6 +32,7 @@ import PreferencesContext from '../../../Preferences/PreferencesContext';
|
||||
import PlanRecommendationRow from './PlanRecommendationRow';
|
||||
import { SurveyCard } from './SurveyCard';
|
||||
import PlaceholderLoader from '../../../../UI/PlaceholderLoader';
|
||||
import PromotionsSlideshow from '../../../../Promotions/PromotionsSlideshow';
|
||||
|
||||
const styles = {
|
||||
textTutorialContent: {
|
||||
@@ -300,6 +301,16 @@ const RecommendationList = ({
|
||||
</SectionRow>
|
||||
);
|
||||
|
||||
items.push(
|
||||
<SectionRow key="promotions">
|
||||
<Text size="section-title" noMargin>
|
||||
<Trans>Discover the ecosystem</Trans>
|
||||
</Text>
|
||||
<Spacer />
|
||||
<PromotionsSlideshow />
|
||||
</SectionRow>
|
||||
);
|
||||
|
||||
if (recommendedTextTutorials.length) {
|
||||
items.push(
|
||||
<SectionRow key="texts">
|
||||
|
@@ -4,7 +4,10 @@ import GDevelopThemeContext from '../../../../UI/Theme/GDevelopThemeContext';
|
||||
import RaisedButton from '../../../../UI/RaisedButton';
|
||||
import { Trans } from '@lingui/macro';
|
||||
import { Line, Spacer } from '../../../../UI/Grid';
|
||||
import { ColumnStackLayout } from '../../../../UI/Layout';
|
||||
import {
|
||||
ColumnStackLayout,
|
||||
ResponsiveLineStackLayout,
|
||||
} from '../../../../UI/Layout';
|
||||
import Text from '../../../../UI/Text';
|
||||
|
||||
const styles = {
|
||||
@@ -38,37 +41,43 @@ export const SurveyCard = ({
|
||||
|
||||
return (
|
||||
<div style={subscriptionContainerStyle}>
|
||||
<img src="res/start-survey.svg" style={styles.surveyIcon} alt="Survey" />
|
||||
<Line noMargin expand>
|
||||
<ColumnStackLayout alignItems="flex-start" expand>
|
||||
<Text noMargin size="block-title">
|
||||
{hasFilledSurveyAlready ? (
|
||||
<Trans>Have you changed your usage of GDevelop?</Trans>
|
||||
) : (
|
||||
<Trans>Personalize your suggested content</Trans>
|
||||
)}
|
||||
</Text>
|
||||
<Text noMargin size="body">
|
||||
<Trans>
|
||||
Answer a 1-minute survey to personalize your “Get started”
|
||||
content.
|
||||
</Trans>
|
||||
</Text>
|
||||
<Spacer />
|
||||
<RaisedButton
|
||||
label={
|
||||
hasFilledSurveyAlready ? (
|
||||
<Trans>Redo the survey</Trans>
|
||||
<ResponsiveLineStackLayout noMargin>
|
||||
<img
|
||||
src="res/start-survey.svg"
|
||||
style={styles.surveyIcon}
|
||||
alt="Survey"
|
||||
/>
|
||||
<Line noMargin expand>
|
||||
<ColumnStackLayout alignItems="flex-start" expand>
|
||||
<Text noMargin size="block-title">
|
||||
{hasFilledSurveyAlready ? (
|
||||
<Trans>Have you changed your usage of GDevelop?</Trans>
|
||||
) : (
|
||||
<Trans>Start the survey!</Trans>
|
||||
)
|
||||
}
|
||||
primary
|
||||
onClick={onStartSurvey}
|
||||
/>
|
||||
<Spacer />
|
||||
</ColumnStackLayout>
|
||||
</Line>
|
||||
<Trans>Personalize your suggested content</Trans>
|
||||
)}
|
||||
</Text>
|
||||
<Text noMargin size="body">
|
||||
<Trans>
|
||||
Answer a 1-minute survey to personalize your “Get started”
|
||||
content.
|
||||
</Trans>
|
||||
</Text>
|
||||
<Spacer />
|
||||
<RaisedButton
|
||||
label={
|
||||
hasFilledSurveyAlready ? (
|
||||
<Trans>Redo the survey</Trans>
|
||||
) : (
|
||||
<Trans>Start the survey!</Trans>
|
||||
)
|
||||
}
|
||||
primary
|
||||
onClick={onStartSurvey}
|
||||
/>
|
||||
<Spacer />
|
||||
</ColumnStackLayout>
|
||||
</Line>
|
||||
</ResponsiveLineStackLayout>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@@ -628,16 +628,10 @@ const GetStartedSection = ({
|
||||
return (
|
||||
<>
|
||||
<SectionContainer
|
||||
title={
|
||||
profile && profile.username ? (
|
||||
<Trans>Hello {profile.username}!</Trans>
|
||||
) : (
|
||||
<Trans>Hello!</Trans>
|
||||
)
|
||||
}
|
||||
title={<Trans>Start making games</Trans>}
|
||||
renderSubtitle={renderSubtitle}
|
||||
flexBody
|
||||
showAnnouncementsAndPromotions
|
||||
showUrgentAnnouncements
|
||||
>
|
||||
<RecommendationList
|
||||
authenticatedUser={authenticatedUser}
|
||||
|
@@ -11,11 +11,11 @@ import ProjectManagerIcon from '../../../UI/CustomSvgIcons/ProjectManager';
|
||||
import FloppyIcon from '../../../UI/CustomSvgIcons/Floppy';
|
||||
import Window from '../../../Utils/Window';
|
||||
import optionalRequire from '../../../Utils/OptionalRequire';
|
||||
import { useResponsiveWindowSize } from '../../../UI/Responsive/ResponsiveWindowMeasurer';
|
||||
import TextButton from '../../../UI/TextButton';
|
||||
import IconButton from '../../../UI/IconButton';
|
||||
import { isNativeMobileApp } from '../../../Utils/Platform';
|
||||
import NotificationChip from '../../../UI/User/NotificationChip';
|
||||
import { useResponsiveWindowSize } from '../../../UI/Responsive/ResponsiveWindowMeasurer';
|
||||
const electron = optionalRequire('electron');
|
||||
|
||||
type Props = {|
|
||||
@@ -36,6 +36,7 @@ export const HomePageHeader = ({
|
||||
canSave,
|
||||
}: Props) => {
|
||||
const { isMobile } = useResponsiveWindowSize();
|
||||
|
||||
return (
|
||||
<I18n>
|
||||
{({ i18n }) => (
|
||||
@@ -73,9 +74,9 @@ export const HomePageHeader = ({
|
||||
</Column>
|
||||
<Column>
|
||||
<LineStackLayout noMargin alignItems="center">
|
||||
{!electron && !isNativeMobileApp() && !isMobile && (
|
||||
{!electron && !isNativeMobileApp() && (
|
||||
<FlatButton
|
||||
label={<Trans>Download desktop app</Trans>}
|
||||
label={<Trans>Get the app</Trans>}
|
||||
onClick={() =>
|
||||
Window.openExternalURL('https://gdevelop.io/download')
|
||||
}
|
||||
@@ -83,11 +84,17 @@ export const HomePageHeader = ({
|
||||
)}
|
||||
<UserChip onOpenProfile={onOpenProfile} />
|
||||
<NotificationChip />
|
||||
<TextButton
|
||||
label={i18n.language.toUpperCase()}
|
||||
onClick={onOpenLanguageDialog}
|
||||
icon={<TranslateIcon fontSize="small" />}
|
||||
/>
|
||||
{isMobile ? (
|
||||
<IconButton size="small" onClick={onOpenLanguageDialog}>
|
||||
<TranslateIcon fontSize="small" />
|
||||
</IconButton>
|
||||
) : (
|
||||
<TextButton
|
||||
label={i18n.language.toUpperCase()}
|
||||
onClick={onOpenLanguageDialog}
|
||||
icon={<TranslateIcon fontSize="small" />}
|
||||
/>
|
||||
)}
|
||||
</LineStackLayout>
|
||||
</Column>
|
||||
</LineStackLayout>
|
||||
|
@@ -79,7 +79,7 @@ const HomePageMenuBar = ({
|
||||
const theme = React.useContext(GDevelopThemeContext);
|
||||
const { profile } = React.useContext(AuthenticatedUserContext);
|
||||
const tabsToDisplay = getTabsToDisplay({ profile });
|
||||
const buttons: {
|
||||
const largeScreenOnlyButtons: {
|
||||
label: React.Node,
|
||||
getIcon: GetIconFunction,
|
||||
id: string,
|
||||
@@ -139,29 +139,6 @@ const HomePageMenuBar = ({
|
||||
</IconButton>
|
||||
);
|
||||
})}
|
||||
<span
|
||||
style={{
|
||||
width: 1,
|
||||
backgroundColor: theme.home.separator.color,
|
||||
height: '70%',
|
||||
margin: '0 3px',
|
||||
}}
|
||||
/>
|
||||
{buttons.map(({ label, onClick, getIcon, id }) => (
|
||||
<IconButton
|
||||
color="default"
|
||||
key={id}
|
||||
disableRipple
|
||||
disableFocusRipple
|
||||
style={styles.mobileButton}
|
||||
onClick={onClick}
|
||||
id={id}
|
||||
>
|
||||
<span style={styles.buttonLabel}>
|
||||
{getIcon({ color: 'secondary', fontSize: 'inherit' })}
|
||||
</span>
|
||||
</IconButton>
|
||||
))}
|
||||
</ToolbarGroup>
|
||||
</Toolbar>
|
||||
</Paper>
|
||||
@@ -198,7 +175,7 @@ const HomePageMenuBar = ({
|
||||
|
||||
<div style={styles.bottomButtonsContainer}>
|
||||
<Column>
|
||||
{buttons.map(({ label, getIcon, onClick, id }) => (
|
||||
{largeScreenOnlyButtons.map(({ label, getIcon, onClick, id }) => (
|
||||
<VerticalTabButton
|
||||
key={id}
|
||||
label={label}
|
||||
|
@@ -99,85 +99,63 @@ const GuidedLessons = ({ selectInAppTutorial, lessonsIds }: Props) => {
|
||||
return tutorialProgress.progress[0]; // guided lessons only have one part.
|
||||
};
|
||||
|
||||
const lessonsCompleted = guidedLessonsIds.reduce((acc, tutorialId) => {
|
||||
const tutorialProgress = getTutorialPartProgress({ tutorialId }) || 0;
|
||||
return tutorialProgress === 100 ? acc + 1 : acc;
|
||||
}, 0);
|
||||
const displayedGuidedLessonsIds = lessonsIds || guidedLessonsIds;
|
||||
|
||||
const lessonsCompleted = displayedGuidedLessonsIds.reduce(
|
||||
(acc, tutorialId) => {
|
||||
const tutorialProgress = getTutorialPartProgress({ tutorialId }) || 0;
|
||||
return tutorialProgress === 100 ? acc + 1 : acc;
|
||||
},
|
||||
0
|
||||
);
|
||||
const lessonsProgress = Math.round(
|
||||
(lessonsCompleted / guidedLessonsIds.length) * 100
|
||||
(lessonsCompleted / displayedGuidedLessonsIds.length) * 100
|
||||
);
|
||||
|
||||
const guidedLessonCards = [
|
||||
{
|
||||
id: JOYSTICK_IN_APP_TUTORIAL_ID,
|
||||
title: t`Add Joystick controls`,
|
||||
title: t`Joystick controls`,
|
||||
description: t`Learn how to add a joystick to control the player.`,
|
||||
keyPoints: [
|
||||
t`Add a layer`,
|
||||
t`Download and use a prefab`,
|
||||
t`Use a behavior`,
|
||||
],
|
||||
durationInMinutes: 1,
|
||||
renderImage: props => <Joystick {...props} />,
|
||||
},
|
||||
{
|
||||
id: HEALTH_BAR_IN_APP_TUTORIAL_ID,
|
||||
title: t`Display a Health bar for the player`,
|
||||
title: t`Health bar`,
|
||||
description: t`Learn how to display the health of a player on the foreground.`,
|
||||
keyPoints: [t`Add a layer`, t`Download and use a prefab`],
|
||||
durationInMinutes: 2,
|
||||
renderImage: props => <HealthBar {...props} />,
|
||||
},
|
||||
{
|
||||
id: OBJECT_3D_IN_APP_TUTORIAL_ID,
|
||||
title: t`Add a 3D object`,
|
||||
description: t`Learn how to add a 3D object to your game.`,
|
||||
keyPoints: [
|
||||
t`Add a 3D box`,
|
||||
t`Add a behavior`,
|
||||
t`Update the elevation of a 3D box`,
|
||||
],
|
||||
title: t`3D box`,
|
||||
description: t`Learn how to add a 3D box to your game.`,
|
||||
durationInMinutes: 2,
|
||||
renderImage: props => <Object3D {...props} />,
|
||||
},
|
||||
{
|
||||
id: CAMERA_PARALLAX_IN_APP_TUTORIAL_ID,
|
||||
title: t`Improve background and camera`,
|
||||
title: t`Background`,
|
||||
description: t`Learn how to create a parallax background as well as a camera that follows the player.`,
|
||||
keyPoints: [
|
||||
t`Add an extension`,
|
||||
t`Add a layer`,
|
||||
t`Use a tiled sprite`,
|
||||
t`Control the camera`,
|
||||
],
|
||||
durationInMinutes: 2,
|
||||
renderImage: props => <Parallax {...props} />,
|
||||
},
|
||||
{
|
||||
id: TIMER_IN_APP_TUTORIAL_ID,
|
||||
title: t`Use a timer`,
|
||||
title: t`Timer`,
|
||||
description: t`Learn how to use a timer to count a score.`,
|
||||
keyPoints: [
|
||||
t`Create and use a timer`,
|
||||
t`Create and modify a text`,
|
||||
t`Build an expression`,
|
||||
],
|
||||
durationInMinutes: 2,
|
||||
renderImage: props => <Timer {...props} />,
|
||||
},
|
||||
{
|
||||
id: PLINKO_MULTIPLIER_IN_APP_TUTORIAL_ID,
|
||||
title: t`Add score multiplier`,
|
||||
title: t`Score multiplier`,
|
||||
description: t`Learn how to manipulate a score by adding collectibles.`,
|
||||
keyPoints: [
|
||||
t`Create a variable`,
|
||||
t`Use & manipulate a variable`,
|
||||
t`Build an expression`,
|
||||
],
|
||||
durationInMinutes: 3,
|
||||
renderImage: props => <MultiplierScore {...props} />,
|
||||
},
|
||||
].filter(item => (lessonsIds ? lessonsIds.includes(item.id) : true));
|
||||
].filter(item => displayedGuidedLessonsIds.includes(item.id));
|
||||
|
||||
return (
|
||||
<Line>
|
||||
@@ -191,20 +169,18 @@ const GuidedLessons = ({ selectInAppTutorial, lessonsIds }: Props) => {
|
||||
</PlaceholderError>
|
||||
) : (
|
||||
<ColumnStackLayout noMargin>
|
||||
{!lessonsIds && (
|
||||
<Column>
|
||||
<LineStackLayout alignItems="center">
|
||||
{lessonsProgress !== 100 ? (
|
||||
<Text displayInlineAsSpan noMargin size="body2">
|
||||
{lessonsProgress}%
|
||||
</Text>
|
||||
) : (
|
||||
<Trophy />
|
||||
)}
|
||||
<ColoredLinearProgress value={lessonsProgress} />
|
||||
</LineStackLayout>
|
||||
</Column>
|
||||
)}
|
||||
<Column>
|
||||
<LineStackLayout alignItems="center">
|
||||
{lessonsProgress !== 100 ? (
|
||||
<Text displayInlineAsSpan noMargin size="body2">
|
||||
{lessonsProgress}%
|
||||
</Text>
|
||||
) : (
|
||||
<Trophy />
|
||||
)}
|
||||
<ColoredLinearProgress value={lessonsProgress} />
|
||||
</LineStackLayout>
|
||||
</Column>
|
||||
<GridList
|
||||
cols={getColumnsFromWindowSize(windowSize, isLandscape)}
|
||||
style={styles.grid}
|
||||
@@ -217,7 +193,6 @@ const GuidedLessons = ({ selectInAppTutorial, lessonsIds }: Props) => {
|
||||
title={item.title}
|
||||
description={item.description}
|
||||
durationInMinutes={item.durationInMinutes}
|
||||
keyPoints={item.keyPoints}
|
||||
renderImage={item.renderImage}
|
||||
progress={getTutorialPartProgress({ tutorialId: item.id })}
|
||||
onClick={() => selectInAppTutorial(item.id)}
|
||||
|
@@ -4,10 +4,8 @@ import { Trans } from '@lingui/macro';
|
||||
import * as React from 'react';
|
||||
import Dialog, { DialogPrimaryButton } from '../../../../UI/Dialog';
|
||||
import FlatButton from '../../../../UI/FlatButton';
|
||||
import { Line, Column } from '../../../../UI/Grid';
|
||||
import { Line } from '../../../../UI/Grid';
|
||||
import { ColumnStackLayout } from '../../../../UI/Layout';
|
||||
import InAppTutorialContext from '../../../../InAppTutorial/InAppTutorialContext';
|
||||
import { getLanguageLabelForLocale } from '../../../../Utils/i18n/MessageByLocale';
|
||||
import Text from '../../../../UI/Text';
|
||||
import {
|
||||
FLING_GAME_IN_APP_TUTORIAL_ID,
|
||||
@@ -26,15 +24,6 @@ const styles = {
|
||||
},
|
||||
};
|
||||
|
||||
type Props = {|
|
||||
open: boolean,
|
||||
tutorialId: string,
|
||||
onClose: () => void,
|
||||
tutorialCompletionStatus: 'notStarted' | 'started' | 'complete',
|
||||
isProjectOpened?: boolean,
|
||||
startTutorial: (scenario: 'resume' | 'startOver' | 'start') => Promise<void>,
|
||||
|};
|
||||
|
||||
const getGuidedLessonContent = ({
|
||||
learningKeys,
|
||||
}: {
|
||||
@@ -44,12 +33,6 @@ const getGuidedLessonContent = ({
|
||||
<Text>
|
||||
<Trans>You're about to start this guided lesson.</Trans>
|
||||
</Text>
|
||||
<Text>
|
||||
<Trans>
|
||||
A new project will be opened, so before beginning please ensure you have
|
||||
closed and saved your current project.
|
||||
</Trans>
|
||||
</Text>
|
||||
<Text>
|
||||
<Trans>In this tutorial you will learn:</Trans>
|
||||
</Text>
|
||||
@@ -105,7 +88,6 @@ const titleAndContentByKey = {
|
||||
content: getGuidedLessonContent({
|
||||
learningKeys: [
|
||||
<Trans>Add a background with parallax effect</Trans>,
|
||||
<Trans>Add a new layer</Trans>,
|
||||
<Trans>Add an extension</Trans>,
|
||||
<Trans>Use basic camera movements to follow the player</Trans>,
|
||||
],
|
||||
@@ -117,8 +99,8 @@ const titleAndContentByKey = {
|
||||
),
|
||||
content: getGuidedLessonContent({
|
||||
learningKeys: [
|
||||
<Trans>Add a new layer</Trans>,
|
||||
<Trans>Use a prefab to display the player's health bar</Trans>,
|
||||
<Trans>Use a prefab for a health bar</Trans>,
|
||||
<Trans>Update the health bar based on the player's health</Trans>,
|
||||
],
|
||||
}),
|
||||
},
|
||||
@@ -126,7 +108,6 @@ const titleAndContentByKey = {
|
||||
title: <Trans>Let's add mobile controls to our game</Trans>,
|
||||
content: getGuidedLessonContent({
|
||||
learningKeys: [
|
||||
<Trans>Add a new layer</Trans>,
|
||||
<Trans>Add a joystick prefab</Trans>,
|
||||
<Trans>Add a behavior</Trans>,
|
||||
],
|
||||
@@ -138,12 +119,21 @@ const titleAndContentByKey = {
|
||||
learningKeys: [
|
||||
<Trans>Add a 3D Box</Trans>,
|
||||
<Trans>Add a behavior</Trans>,
|
||||
<Trans>Update the elevation of a 3D box</Trans>,
|
||||
],
|
||||
}),
|
||||
},
|
||||
};
|
||||
|
||||
type Props = {|
|
||||
open: boolean,
|
||||
tutorialId: string,
|
||||
onClose: () => void,
|
||||
tutorialCompletionStatus: 'notStarted' | 'started' | 'complete',
|
||||
isProjectOpened?: boolean,
|
||||
isProjectOpening: boolean,
|
||||
startTutorial: (scenario: 'resume' | 'startOver' | 'start') => Promise<void>,
|
||||
|};
|
||||
|
||||
const StartInAppTutorialDialog = ({
|
||||
open,
|
||||
tutorialId,
|
||||
@@ -151,33 +141,16 @@ const StartInAppTutorialDialog = ({
|
||||
tutorialCompletionStatus,
|
||||
isProjectOpened,
|
||||
startTutorial,
|
||||
isProjectOpening,
|
||||
}: Props) => {
|
||||
const resumeTutorial = () => startTutorial('resume');
|
||||
const startOverTutorial = () => startTutorial('startOver');
|
||||
const startTutorialForFirstTime = () => startTutorial('start');
|
||||
|
||||
const { getInAppTutorialShortHeader } = React.useContext(
|
||||
InAppTutorialContext
|
||||
);
|
||||
|
||||
const selectedInAppTutorialShortHeader = getInAppTutorialShortHeader(
|
||||
tutorialId
|
||||
);
|
||||
|
||||
const availableLocales = selectedInAppTutorialShortHeader
|
||||
? selectedInAppTutorialShortHeader.availableLocales
|
||||
: null;
|
||||
|
||||
const dialogContentByCompletionStatus = {
|
||||
notStarted: {
|
||||
title: titleAndContentByKey[tutorialId].title,
|
||||
content: titleAndContentByKey[tutorialId].content,
|
||||
availableLocalesLabels: availableLocales
|
||||
? availableLocales.map(locale => [
|
||||
locale,
|
||||
getLanguageLabelForLocale(locale),
|
||||
])
|
||||
: null,
|
||||
primaryAction: {
|
||||
label: <Trans>Yes</Trans>,
|
||||
onClick: startTutorialForFirstTime,
|
||||
@@ -248,12 +221,14 @@ const StartInAppTutorialDialog = ({
|
||||
key="close"
|
||||
label={secondaryAction.label}
|
||||
onClick={secondaryAction.onClick}
|
||||
disabled={isProjectOpening}
|
||||
/>,
|
||||
<DialogPrimaryButton
|
||||
key="start"
|
||||
label={primaryAction.label}
|
||||
primary
|
||||
onClick={primaryAction.onClick}
|
||||
disabled={isProjectOpening}
|
||||
/>,
|
||||
];
|
||||
const secondaryActions = tertiaryAction
|
||||
@@ -262,6 +237,7 @@ const StartInAppTutorialDialog = ({
|
||||
key="other"
|
||||
label={tertiaryAction.label}
|
||||
onClick={tertiaryAction.onClick}
|
||||
disabled={isProjectOpening}
|
||||
/>,
|
||||
]
|
||||
: undefined;
|
||||
@@ -284,20 +260,6 @@ const StartInAppTutorialDialog = ({
|
||||
</div>
|
||||
</Line>
|
||||
{content}
|
||||
{dialogContent.availableLocalesLabels ? (
|
||||
<Column noMargin>
|
||||
<Text>
|
||||
<Trans>
|
||||
This tutorial is available in the following languages:
|
||||
</Trans>
|
||||
</Text>
|
||||
{dialogContent.availableLocalesLabels.map(([locale, label]) => (
|
||||
<Text displayAsListItem noMargin key={locale}>
|
||||
{label}
|
||||
</Text>
|
||||
))}
|
||||
</Column>
|
||||
) : null}
|
||||
<Text>
|
||||
<Trans>Are you ready?</Trans>
|
||||
</Text>
|
||||
|
@@ -162,9 +162,6 @@ const MainPage = ({
|
||||
return (
|
||||
<SectionContainer title={<Trans>Help and guides</Trans>}>
|
||||
<SectionRow>
|
||||
<Text>
|
||||
<Trans>Quick search</Trans>
|
||||
</Text>
|
||||
<WikiSearchBar />
|
||||
</SectionRow>
|
||||
<SectionRow>
|
||||
|
@@ -9,7 +9,6 @@ import { Trans } from '@lingui/macro';
|
||||
import Paper from '../../../UI/Paper';
|
||||
import { LineStackLayout } from '../../../UI/Layout';
|
||||
import { AnnouncementsFeed } from '../../../AnnouncementsFeed';
|
||||
import PromotionsSlideshow from '../../../Promotions/PromotionsSlideshow';
|
||||
import { AnnouncementsFeedContext } from '../../../AnnouncementsFeed/AnnouncementsFeedContext';
|
||||
|
||||
export const SECTION_PADDING = 30;
|
||||
@@ -58,7 +57,7 @@ type Props = {|
|
||||
flexBody?: boolean,
|
||||
renderFooter?: () => React.Node,
|
||||
noScroll?: boolean,
|
||||
showAnnouncementsAndPromotions?: boolean,
|
||||
showUrgentAnnouncements?: boolean,
|
||||
|};
|
||||
|
||||
const SectionContainer = ({
|
||||
@@ -71,7 +70,7 @@ const SectionContainer = ({
|
||||
flexBody,
|
||||
renderFooter,
|
||||
noScroll,
|
||||
showAnnouncementsAndPromotions,
|
||||
showUrgentAnnouncements,
|
||||
}: Props) => {
|
||||
const { isMobile } = useResponsiveWindowSize();
|
||||
const { announcements } = React.useContext(AnnouncementsFeedContext);
|
||||
@@ -94,14 +93,10 @@ const SectionContainer = ({
|
||||
<Column useFullHeight noMargin expand>
|
||||
<Paper style={paperStyle} square background="dark">
|
||||
<Column noOverflowParent expand>
|
||||
{showAnnouncementsAndPromotions && (
|
||||
{showUrgentAnnouncements && (
|
||||
<>
|
||||
<AnnouncementsFeed canClose level="urgent" hideLoader />
|
||||
{announcements && announcements.length > 0 && <Spacer />}
|
||||
<Column noMargin>
|
||||
<PromotionsSlideshow />
|
||||
</Column>
|
||||
<Spacer />
|
||||
</>
|
||||
)}
|
||||
{backAction && (
|
||||
|
@@ -83,6 +83,7 @@ const StoreSection = ({
|
||||
onOpenPrivateGameTemplateListingData={
|
||||
onOpenPrivateGameTemplateListingData
|
||||
}
|
||||
displayPromotions
|
||||
/>
|
||||
{(openedAssetPack || openedAssetShortHeader) && (
|
||||
<Line justifyContent="flex-end">
|
||||
|
@@ -114,7 +114,9 @@ type Props = {|
|
||||
onOpenAbout: () => void,
|
||||
|
||||
// Project creation
|
||||
onOpenNewProjectSetupDialog: () => void,
|
||||
onOpenNewProjectSetupDialog: (
|
||||
initialTab: 'from-scratch' | 'ai' | 'example'
|
||||
) => void,
|
||||
|
||||
// Project save
|
||||
onSave: () => Promise<void>,
|
||||
|
@@ -54,6 +54,13 @@ html {
|
||||
padding-left: env(safe-area-inset-left);
|
||||
}
|
||||
|
||||
/* Helper for avoiding the soft keyboard. See also `getAvoidSoftKeyboardStyle`. */
|
||||
.avoid-soft-keyboard {
|
||||
transform: translateY(calc(-1 * var(--softKeyboardBottomOffset)));
|
||||
transition: transform 0.2s linear;
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
/* Disable selections and web-ish cursors */
|
||||
:not(input):not(textarea):not(canvas):not(code),
|
||||
:not(input):not(textarea):not(canvas):not(code)::after,
|
||||
|
@@ -12,7 +12,9 @@ import AuthenticatedUserContext from '../Profile/AuthenticatedUserContext';
|
||||
|
||||
type Props = {|
|
||||
isProjectOpening: boolean,
|
||||
onOpenNewProjectSetupDialog: () => void,
|
||||
onOpenNewProjectSetupDialog: (
|
||||
initialTab: 'from-scratch' | 'ai' | 'example'
|
||||
) => void,
|
||||
|};
|
||||
|
||||
const useExampleOrGameTemplateDialogs = ({
|
||||
@@ -137,7 +139,7 @@ const useExampleOrGameTemplateDialogs = ({
|
||||
<ExampleDialog
|
||||
isOpening={isProjectOpening}
|
||||
exampleShortHeader={selectedExampleShortHeader}
|
||||
onOpen={onOpenNewProjectSetupDialog}
|
||||
onOpen={() => onOpenNewProjectSetupDialog('example')}
|
||||
onClose={() => setSelectedExampleShortHeader(null)}
|
||||
/>
|
||||
)}
|
||||
@@ -148,7 +150,9 @@ const useExampleOrGameTemplateDialogs = ({
|
||||
selectedPrivateGameTemplate.privateGameTemplateListingData
|
||||
}
|
||||
isPurchaseDialogOpen={!!purchasingGameTemplateListingData}
|
||||
onCreateWithGameTemplate={onOpenNewProjectSetupDialog}
|
||||
onCreateWithGameTemplate={() =>
|
||||
onOpenNewProjectSetupDialog('example')
|
||||
}
|
||||
onGameTemplateOpen={privateGameTemplateListingData =>
|
||||
setSelectedPrivateGameTemplate({
|
||||
privateGameTemplateListingData,
|
||||
|
@@ -359,9 +359,9 @@ const MainFrame = (props: Props) => {
|
||||
openPreferencesDialog,
|
||||
] = React.useState<boolean>(false);
|
||||
const [
|
||||
newProjectSetupDialogOpen,
|
||||
setNewProjectSetupDialogOpen,
|
||||
] = React.useState<boolean>(false);
|
||||
newProjectSetupDialogInitialTab,
|
||||
setNewProjectSetupDialogInitialTab,
|
||||
] = React.useState<null | 'from-scratch' | 'ai' | 'example'>(null);
|
||||
|
||||
const [isProjectOpening, setIsProjectOpening] = React.useState<boolean>(
|
||||
false
|
||||
@@ -498,7 +498,7 @@ const MainFrame = (props: Props) => {
|
||||
openExampleStoreDialog,
|
||||
} = useExampleOrGameTemplateDialogs({
|
||||
isProjectOpening,
|
||||
onOpenNewProjectSetupDialog: () => setNewProjectSetupDialogOpen(true),
|
||||
onOpenNewProjectSetupDialog: setNewProjectSetupDialogInitialTab,
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -1144,7 +1144,7 @@ const MainFrame = (props: Props) => {
|
||||
},
|
||||
getStorageProviderOperations,
|
||||
afterCreatingProject: async ({ project, editorTabs, oldProjectId }) => {
|
||||
setNewProjectSetupDialogOpen(false);
|
||||
setNewProjectSetupDialogInitialTab(null);
|
||||
closeExampleStoreDialog({ deselectExampleAndGameTemplate: true });
|
||||
findLeaderboardsToReplace(project, oldProjectId);
|
||||
openSceneOrProjectManager({
|
||||
@@ -2960,7 +2960,7 @@ const MainFrame = (props: Props) => {
|
||||
onLaunchDebugPreview: launchDebuggerAndPreview,
|
||||
onLaunchNetworkPreview: launchNetworkPreview,
|
||||
onOpenHomePage: openHomePage,
|
||||
onCreateBlank: () => setNewProjectSetupDialogOpen(true),
|
||||
onCreateBlank: () => setNewProjectSetupDialogInitialTab('from-scratch'),
|
||||
onOpenProject: () => openOpenFromStorageProviderDialog(),
|
||||
onSaveProject: saveProject,
|
||||
onSaveProjectAs: saveProjectAs,
|
||||
@@ -3020,7 +3020,7 @@ const MainFrame = (props: Props) => {
|
||||
onExportProject: () => openShareDialog('publish'),
|
||||
onInviteCollaborators: () => openShareDialog('invite'),
|
||||
onCreateProject: openExampleStoreDialog,
|
||||
onCreateBlank: () => setNewProjectSetupDialogOpen(true),
|
||||
onCreateBlank: () => setNewProjectSetupDialogInitialTab('from-scratch'),
|
||||
onOpenProjectManager: () => openProjectManager(true),
|
||||
onOpenHomePage: openHomePage,
|
||||
onOpenDebugger: openDebugger,
|
||||
@@ -3224,9 +3224,7 @@ const MainFrame = (props: Props) => {
|
||||
canInstallPrivateAsset,
|
||||
onChooseProject: () => openOpenFromStorageProviderDialog(),
|
||||
onOpenRecentFile: openFromFileMetadataWithStorageProvider,
|
||||
onOpenNewProjectSetupDialog: () => {
|
||||
setNewProjectSetupDialogOpen(true);
|
||||
},
|
||||
onOpenNewProjectSetupDialog: setNewProjectSetupDialogInitialTab,
|
||||
onOpenProjectManager: () => openProjectManager(true),
|
||||
onCloseProject: () => askToCloseProject(),
|
||||
onOpenExampleStore: openExampleStoreDialog,
|
||||
@@ -3241,7 +3239,7 @@ const MainFrame = (props: Props) => {
|
||||
privateGameTemplateListingData,
|
||||
openDialog: false,
|
||||
});
|
||||
setNewProjectSetupDialogOpen(true);
|
||||
setNewProjectSetupDialogInitialTab('example');
|
||||
},
|
||||
onOpenProfile: () => openProfileDialog(true),
|
||||
onOpenLanguageDialog: () => openLanguageDialog(true),
|
||||
@@ -3366,11 +3364,12 @@ const MainFrame = (props: Props) => {
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{newProjectSetupDialogOpen && (
|
||||
{newProjectSetupDialogInitialTab && (
|
||||
<NewProjectSetupDialog
|
||||
initialTab={newProjectSetupDialogInitialTab}
|
||||
authenticatedUser={authenticatedUser}
|
||||
isOpeningProject={isProjectOpening}
|
||||
onClose={() => setNewProjectSetupDialogOpen(false)}
|
||||
onClose={() => setNewProjectSetupDialogInitialTab(null)}
|
||||
onCreateEmptyProject={createEmptyProject}
|
||||
onCreateFromExample={createProjectFromExample}
|
||||
onCreateProjectFromPrivateGameTemplate={
|
||||
@@ -3480,6 +3479,7 @@ const MainFrame = (props: Props) => {
|
||||
onClose={() => {
|
||||
setSelectedInAppTutorialInfo(null);
|
||||
}}
|
||||
isProjectOpening={isProjectOpening}
|
||||
/>
|
||||
)}
|
||||
{state.gdjsDevelopmentWatcherEnabled &&
|
||||
|
@@ -201,15 +201,13 @@ type PolygonsListProps = {|
|
||||
|
||||
// Sprite size is useful to make sure polygon vertices
|
||||
// are not put outside the sprite bounding box, which is not supported:
|
||||
spriteWidth: number,
|
||||
spriteHeight: number,
|
||||
spriteSize: [number, number],
|
||||
|};
|
||||
|
||||
const PolygonsList = (props: PolygonsListProps) => {
|
||||
const {
|
||||
polygons,
|
||||
spriteHeight,
|
||||
spriteWidth,
|
||||
spriteSize,
|
||||
onPolygonsUpdated,
|
||||
onSetFullImageCollisionMask,
|
||||
onSetAutomaticallyAdaptCollisionMasks,
|
||||
@@ -218,6 +216,7 @@ const PolygonsList = (props: PolygonsListProps) => {
|
||||
selectedVerticePtr,
|
||||
} = props;
|
||||
|
||||
const [spriteWidth, spriteHeight] = spriteSize;
|
||||
const addCollisionMask = React.useCallback(
|
||||
() => {
|
||||
const newPolygon = gd.Polygon2d.createRectangle(
|
||||
|
@@ -83,8 +83,9 @@ const CollisionMasksEditor = ({
|
||||
null
|
||||
);
|
||||
|
||||
const [spriteWidth, setSpriteWidth] = React.useState(0);
|
||||
const [spriteHeight, setSpriteHeight] = React.useState(0);
|
||||
const [currentSpriteSize, setCurrentSpriteSize] = React.useState<
|
||||
[number, number]
|
||||
>([0, 0]);
|
||||
const forceUpdate = useForceUpdate();
|
||||
|
||||
const { showConfirmation } = useAlertDialog();
|
||||
@@ -245,11 +246,6 @@ const CollisionMasksEditor = ({
|
||||
[sameCollisionMasksForAnimations, updateCollisionMasks, showConfirmation]
|
||||
);
|
||||
|
||||
const setCurrentSpriteSize = (spriteWidth: number, spriteHeight: number) => {
|
||||
setSpriteWidth(spriteWidth);
|
||||
setSpriteHeight(spriteHeight);
|
||||
};
|
||||
|
||||
const onSetAutomaticallyAdaptCollisionMasks = React.useCallback(
|
||||
async value => {
|
||||
// If enabling automatic while custom was selected, then ask for confirmation.
|
||||
@@ -334,7 +330,7 @@ const CollisionMasksEditor = ({
|
||||
project,
|
||||
resourceName
|
||||
)}
|
||||
onSize={setCurrentSpriteSize}
|
||||
onImageSize={setCurrentSpriteSize}
|
||||
renderOverlay={overlayProps =>
|
||||
sprite && (
|
||||
<CollisionMasksPreview
|
||||
@@ -410,8 +406,7 @@ const CollisionMasksEditor = ({
|
||||
onHoverVertice={setHighlightedVerticePtr}
|
||||
onClickVertice={setSelectedVerticePtr}
|
||||
selectedVerticePtr={selectedVerticePtr}
|
||||
spriteWidth={spriteWidth}
|
||||
spriteHeight={spriteHeight}
|
||||
spriteSize={currentSpriteSize}
|
||||
/>
|
||||
</React.Fragment>
|
||||
)}
|
||||
|
@@ -1,10 +1,8 @@
|
||||
// @flow
|
||||
import { Trans } from '@lingui/macro';
|
||||
import * as React from 'react';
|
||||
import { TableRow, TableRowColumn } from '../../../../UI/Table';
|
||||
import IconButton from '../../../../UI/IconButton';
|
||||
import SemiControlledTextField from '../../../../UI/SemiControlledTextField';
|
||||
import Text from '../../../../UI/Text';
|
||||
import { roundTo } from '../../../../Utils/Mathematics';
|
||||
import { Column } from '../../../../UI/Grid';
|
||||
import GDevelopThemeContext from '../../../../UI/Theme/GDevelopThemeContext';
|
||||
@@ -63,64 +61,50 @@ const PointRow = ({ pointX, pointY, ...props }: Props) => {
|
||||
</TableRowColumn>
|
||||
<TableRowColumn style={styles.coordinateColumn} padding="none">
|
||||
<Column>
|
||||
{!props.isAutomatic ? (
|
||||
<SemiControlledTextField
|
||||
margin="none"
|
||||
inputStyle={
|
||||
props.selected
|
||||
? { color: gdevelopTheme.listItem.selectedTextColor }
|
||||
: undefined
|
||||
}
|
||||
value={roundTo(pointX, POINT_COORDINATE_PRECISION).toString()}
|
||||
type="number"
|
||||
step={0.5}
|
||||
id="point-x"
|
||||
onChange={value => {
|
||||
const valueAsNumber = parseFloat(value);
|
||||
if (!isNaN(valueAsNumber)) props.onChangePointX(valueAsNumber);
|
||||
}}
|
||||
onBlur={event => {
|
||||
props.onChangePointX(
|
||||
parseFloat(event.currentTarget.value) || 0
|
||||
);
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<Text noMargin>
|
||||
<Trans>(auto)</Trans>
|
||||
</Text>
|
||||
)}
|
||||
<SemiControlledTextField
|
||||
margin="none"
|
||||
inputStyle={
|
||||
props.selected
|
||||
? { color: gdevelopTheme.listItem.selectedTextColor }
|
||||
: undefined
|
||||
}
|
||||
value={roundTo(pointX, POINT_COORDINATE_PRECISION).toString()}
|
||||
type="number"
|
||||
step={0.5}
|
||||
id="point-x"
|
||||
onChange={value => {
|
||||
const valueAsNumber = parseFloat(value);
|
||||
if (!isNaN(valueAsNumber)) props.onChangePointX(valueAsNumber);
|
||||
}}
|
||||
onBlur={event => {
|
||||
props.onChangePointX(parseFloat(event.currentTarget.value) || 0);
|
||||
}}
|
||||
disabled={props.isAutomatic}
|
||||
/>
|
||||
</Column>
|
||||
</TableRowColumn>
|
||||
<TableRowColumn style={styles.coordinateColumn} padding="none">
|
||||
<Column>
|
||||
{!props.isAutomatic ? (
|
||||
<SemiControlledTextField
|
||||
margin="none"
|
||||
inputStyle={
|
||||
props.selected
|
||||
? { color: gdevelopTheme.listItem.selectedTextColor }
|
||||
: undefined
|
||||
}
|
||||
value={roundTo(pointY, POINT_COORDINATE_PRECISION).toString()}
|
||||
type="number"
|
||||
step={0.5}
|
||||
id="point-y"
|
||||
onChange={value => {
|
||||
const valueAsNumber = parseFloat(value);
|
||||
if (!isNaN(valueAsNumber)) props.onChangePointY(valueAsNumber);
|
||||
}}
|
||||
onBlur={event => {
|
||||
props.onChangePointY(
|
||||
parseFloat(event.currentTarget.value) || 0
|
||||
);
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<Text noMargin>
|
||||
<Trans>(auto)</Trans>
|
||||
</Text>
|
||||
)}
|
||||
<SemiControlledTextField
|
||||
margin="none"
|
||||
inputStyle={
|
||||
props.selected
|
||||
? { color: gdevelopTheme.listItem.selectedTextColor }
|
||||
: undefined
|
||||
}
|
||||
value={roundTo(pointY, POINT_COORDINATE_PRECISION).toString()}
|
||||
type="number"
|
||||
step={0.5}
|
||||
id="point-y"
|
||||
onChange={value => {
|
||||
const valueAsNumber = parseFloat(value);
|
||||
if (!isNaN(valueAsNumber)) props.onChangePointY(valueAsNumber);
|
||||
}}
|
||||
onBlur={event => {
|
||||
props.onChangePointY(parseFloat(event.currentTarget.value) || 0);
|
||||
}}
|
||||
disabled={props.isAutomatic}
|
||||
/>
|
||||
</Column>
|
||||
</TableRowColumn>
|
||||
<TableRowColumn style={styles.toolColumn}>
|
||||
|
@@ -26,6 +26,7 @@ type PointsListBodyProps = {|
|
||||
onSelectPoint: (pointName: string) => void,
|
||||
onRenamedPoint: (oldName: string, newName: string) => void,
|
||||
selectedPointName: ?string,
|
||||
spriteSize: [number, number],
|
||||
|};
|
||||
|
||||
const PointsListBody = (props: PointsListBodyProps) => {
|
||||
@@ -138,13 +139,19 @@ const PointsListBody = (props: PointsListBodyProps) => {
|
||||
selected={'Origin' === props.selectedPointName}
|
||||
/>
|
||||
);
|
||||
|
||||
const isDefaultCenterPoint = pointsContainer.isDefaultCenterPoint();
|
||||
const centerRow = (
|
||||
<PointRow
|
||||
key={'center-point-row'}
|
||||
pointName="Center"
|
||||
isAutomatic={pointsContainer.isDefaultCenterPoint()}
|
||||
pointX={centerPoint.getX()}
|
||||
pointY={centerPoint.getY()}
|
||||
isAutomatic={isDefaultCenterPoint}
|
||||
pointX={
|
||||
isDefaultCenterPoint ? props.spriteSize[0] / 2 : centerPoint.getX()
|
||||
}
|
||||
pointY={
|
||||
isDefaultCenterPoint ? props.spriteSize[1] / 2 : centerPoint.getY()
|
||||
}
|
||||
onChangePointX={updateCenterPointX}
|
||||
onChangePointY={updateCenterPointY}
|
||||
onPointerEnter={props.onHoverPoint}
|
||||
@@ -180,6 +187,7 @@ type PointsListProps = {|
|
||||
onSelectPoint: (pointName: ?string) => void,
|
||||
onRenamedPoint: (oldName: string, newName: string) => void,
|
||||
selectedPointName: ?string,
|
||||
spriteSize: [number, number],
|
||||
|};
|
||||
|
||||
const PointsList = (props: PointsListProps) => {
|
||||
@@ -207,6 +215,7 @@ const PointsList = (props: PointsListProps) => {
|
||||
selectedPointName={props.selectedPointName}
|
||||
onPointsUpdated={props.onPointsUpdated}
|
||||
onRenamedPoint={props.onRenamedPoint}
|
||||
spriteSize={props.spriteSize}
|
||||
/>
|
||||
</Table>
|
||||
<Spacer />
|
||||
|
@@ -79,6 +79,10 @@ const PointsEditor = ({
|
||||
setHighlightedPointName,
|
||||
] = React.useState<?string>(null);
|
||||
|
||||
const [currentSpriteSize, setCurrentSpriteSize] = React.useState<
|
||||
[number, number]
|
||||
>([0, 0]);
|
||||
|
||||
const forceUpdate = useForceUpdate();
|
||||
const { showConfirmation } = useAlertDialog();
|
||||
|
||||
@@ -224,6 +228,7 @@ const PointsEditor = ({
|
||||
project,
|
||||
resourceName
|
||||
)}
|
||||
onImageSize={setCurrentSpriteSize}
|
||||
renderOverlay={overlayProps =>
|
||||
sprite && (
|
||||
<PointsPreview
|
||||
@@ -289,6 +294,7 @@ const PointsEditor = ({
|
||||
onHoverPoint={setHighlightedPointName}
|
||||
onSelectPoint={setSelectedPointName}
|
||||
onRenamedPoint={onRenamedPoint}
|
||||
spriteSize={currentSpriteSize}
|
||||
/>
|
||||
)}
|
||||
{!sprite && (
|
||||
|
@@ -269,7 +269,6 @@ const EditProfileDialog = ({
|
||||
label={<Trans>Delete my account</Trans>}
|
||||
disabled={actionInProgress}
|
||||
key="delete"
|
||||
primary={false}
|
||||
onClick={onDeleteAccount}
|
||||
/>,
|
||||
];
|
||||
|
279
newIDE/app/src/Profile/Subscription/CancelReasonDialog.js
Normal file
279
newIDE/app/src/Profile/Subscription/CancelReasonDialog.js
Normal file
@@ -0,0 +1,279 @@
|
||||
// @flow
|
||||
import { Trans, t } from '@lingui/macro';
|
||||
import { I18n } from '@lingui/react';
|
||||
import * as React from 'react';
|
||||
import Dialog, { DialogPrimaryButton } from '../../UI/Dialog';
|
||||
import AuthenticatedUserContext from '../AuthenticatedUserContext';
|
||||
import { changeUserSubscription } from '../../Utils/GDevelopServices/Usage';
|
||||
import { ColumnStackLayout, LineStackLayout } from '../../UI/Layout';
|
||||
import useAlertDialog from '../../UI/Alert/useAlertDialog';
|
||||
import GDevelopGLogo from '../../UI/CustomSvgIcons/GDevelopGLogo';
|
||||
import Form from '../../UI/Form';
|
||||
import Text from '../../UI/Text';
|
||||
import { Spacer } from '../../UI/Grid';
|
||||
import TextField from '../../UI/TextField';
|
||||
import Checkbox from '../../UI/Checkbox';
|
||||
import FlatButton from '../../UI/FlatButton';
|
||||
import StarIcon from '../../UI/CustomSvgIcons/Star';
|
||||
|
||||
type Props = {|
|
||||
onClose: () => void,
|
||||
onCloseAfterSuccess: () => void,
|
||||
|};
|
||||
|
||||
const CancelReasonDialog = ({ onClose, onCloseAfterSuccess }: Props) => {
|
||||
const [isCancelingSubscription, setIsCancelingSubscription] = React.useState(
|
||||
false
|
||||
);
|
||||
const [hasCanceledSubscription, setHasCanceledSubscription] = React.useState(
|
||||
false
|
||||
);
|
||||
const [
|
||||
stoppedMakingGamesChecked,
|
||||
setStoppedMakingGamesChecked,
|
||||
] = React.useState(false);
|
||||
const [strugglingChecked, setStrugglingChecked] = React.useState(false);
|
||||
const [
|
||||
preferFreeVersionChecked,
|
||||
setPreferFreeVersionChecked,
|
||||
] = React.useState(false);
|
||||
const [missingFeatureChecked, setMissingFeatureChecked] = React.useState(
|
||||
false
|
||||
);
|
||||
const [qualityIssuesChecked, setQualityIssuesChecked] = React.useState(false);
|
||||
const [otherChecked, setOtherChecked] = React.useState(false);
|
||||
const [freeText, setFreeText] = React.useState('');
|
||||
const authenticatedUser = React.useContext(AuthenticatedUserContext);
|
||||
const { showAlert } = useAlertDialog();
|
||||
|
||||
const canSubmit =
|
||||
(stoppedMakingGamesChecked ||
|
||||
strugglingChecked ||
|
||||
preferFreeVersionChecked ||
|
||||
qualityIssuesChecked ||
|
||||
missingFeatureChecked ||
|
||||
otherChecked) &&
|
||||
((!missingFeatureChecked && !otherChecked) || freeText.trim().length > 0);
|
||||
|
||||
const cancelPlan = React.useCallback(
|
||||
async () => {
|
||||
if (isCancelingSubscription || !canSubmit) return;
|
||||
const {
|
||||
getAuthorizationHeader,
|
||||
subscription,
|
||||
profile,
|
||||
} = authenticatedUser;
|
||||
if (!profile || !subscription) return;
|
||||
setIsCancelingSubscription(true);
|
||||
try {
|
||||
await changeUserSubscription(
|
||||
getAuthorizationHeader,
|
||||
profile.id,
|
||||
{
|
||||
planId: null,
|
||||
},
|
||||
{
|
||||
cancelImmediately: false,
|
||||
cancelReasons: {
|
||||
'stopped-making-games': stoppedMakingGamesChecked,
|
||||
'struggling-with-gdevelop': strugglingChecked,
|
||||
'prefer-free-version': preferFreeVersionChecked,
|
||||
'missing-feature': missingFeatureChecked,
|
||||
'quality-issues': qualityIssuesChecked,
|
||||
other: otherChecked,
|
||||
freeText: freeText,
|
||||
},
|
||||
}
|
||||
);
|
||||
await authenticatedUser.onRefreshSubscription();
|
||||
setHasCanceledSubscription(true);
|
||||
} catch (rawError) {
|
||||
await authenticatedUser.onRefreshSubscription();
|
||||
console.error('Error while canceling subscription:', rawError);
|
||||
showAlert({
|
||||
title: t`Could not cancel your subscription`,
|
||||
message: t`There was an error while canceling your subscription. Verify your internet connection or try again later.`,
|
||||
});
|
||||
} finally {
|
||||
setIsCancelingSubscription(false);
|
||||
}
|
||||
},
|
||||
[
|
||||
authenticatedUser,
|
||||
showAlert,
|
||||
isCancelingSubscription,
|
||||
canSubmit,
|
||||
freeText,
|
||||
stoppedMakingGamesChecked,
|
||||
strugglingChecked,
|
||||
preferFreeVersionChecked,
|
||||
qualityIssuesChecked,
|
||||
missingFeatureChecked,
|
||||
otherChecked,
|
||||
]
|
||||
);
|
||||
|
||||
const isLoading =
|
||||
!authenticatedUser.subscription ||
|
||||
!authenticatedUser.profile ||
|
||||
isCancelingSubscription;
|
||||
|
||||
const actions = hasCanceledSubscription
|
||||
? [
|
||||
<DialogPrimaryButton
|
||||
label={<Trans>Close</Trans>}
|
||||
key="close"
|
||||
onClick={onCloseAfterSuccess}
|
||||
primary
|
||||
/>,
|
||||
]
|
||||
: [
|
||||
<DialogPrimaryButton
|
||||
label={<Trans>Submit and cancel</Trans>}
|
||||
key="submit"
|
||||
onClick={cancelPlan}
|
||||
disabled={!canSubmit || isLoading}
|
||||
primary
|
||||
/>,
|
||||
];
|
||||
|
||||
const secondaryActions = hasCanceledSubscription
|
||||
? []
|
||||
: [
|
||||
<FlatButton
|
||||
label={<Trans>Back</Trans>}
|
||||
key="back"
|
||||
onClick={onClose}
|
||||
disabled={isLoading}
|
||||
/>,
|
||||
];
|
||||
|
||||
return (
|
||||
<I18n>
|
||||
{({ i18n }) => (
|
||||
<Dialog
|
||||
title={null}
|
||||
actions={actions}
|
||||
secondaryActions={secondaryActions}
|
||||
open
|
||||
cannotBeDismissed
|
||||
onApply={cancelPlan}
|
||||
maxWidth="sm"
|
||||
>
|
||||
{hasCanceledSubscription ? (
|
||||
<ColumnStackLayout
|
||||
expand
|
||||
justifyContent="center"
|
||||
alignItems="center"
|
||||
>
|
||||
<GDevelopGLogo fontSize="large" />
|
||||
<Text size="block-title" align="center">
|
||||
<Trans>Your subscription has been canceled</Trans>
|
||||
</Text>
|
||||
<LineStackLayout noMargin alignItems="center">
|
||||
<StarIcon />
|
||||
<Text size="sub-title" align="center">
|
||||
<Trans>Thank you for your feedback</Trans>
|
||||
</Text>
|
||||
</LineStackLayout>
|
||||
</ColumnStackLayout>
|
||||
) : (
|
||||
<ColumnStackLayout
|
||||
expand
|
||||
justifyContent="center"
|
||||
alignItems="center"
|
||||
>
|
||||
<GDevelopGLogo fontSize="large" />
|
||||
<Text size="block-title" align="center">
|
||||
<Trans>Before you go...</Trans>
|
||||
</Text>
|
||||
<Text size="body2" noMargin align="center">
|
||||
<Trans>
|
||||
Your feedback is valuable to help us improve our premium
|
||||
services. Why are you canceling your subscription?
|
||||
</Trans>
|
||||
</Text>
|
||||
<Spacer />
|
||||
<Form
|
||||
onSubmit={cancelPlan}
|
||||
autoComplete="off"
|
||||
name="cancel"
|
||||
fullWidth
|
||||
>
|
||||
<ColumnStackLayout noMargin expand>
|
||||
<Checkbox
|
||||
label={<Trans>I've stopped using GDevelop</Trans>}
|
||||
checked={stoppedMakingGamesChecked}
|
||||
onCheck={(e, checked) =>
|
||||
setStoppedMakingGamesChecked(checked)
|
||||
}
|
||||
disabled={isLoading}
|
||||
/>
|
||||
<Checkbox
|
||||
label={<Trans>I'm struggling to create what I want</Trans>}
|
||||
checked={strugglingChecked}
|
||||
onCheck={(e, checked) => setStrugglingChecked(checked)}
|
||||
disabled={isLoading}
|
||||
/>
|
||||
<Checkbox
|
||||
label={<Trans>The free version is enough for me</Trans>}
|
||||
checked={preferFreeVersionChecked}
|
||||
onCheck={(e, checked) =>
|
||||
setPreferFreeVersionChecked(checked)
|
||||
}
|
||||
disabled={isLoading}
|
||||
/>
|
||||
|
||||
<Checkbox
|
||||
label={
|
||||
<Trans>It's missing a feature (please specify)</Trans>
|
||||
}
|
||||
checked={missingFeatureChecked}
|
||||
onCheck={(e, checked) => setMissingFeatureChecked(checked)}
|
||||
disabled={isLoading}
|
||||
/>
|
||||
<Checkbox
|
||||
label={
|
||||
<Trans>
|
||||
I have encountered bugs or performance problems
|
||||
</Trans>
|
||||
}
|
||||
checked={qualityIssuesChecked}
|
||||
onCheck={(e, checked) => setQualityIssuesChecked(checked)}
|
||||
disabled={isLoading}
|
||||
/>
|
||||
<Checkbox
|
||||
label={<Trans>Other reason (please specify)</Trans>}
|
||||
checked={otherChecked}
|
||||
onCheck={(e, checked) => setOtherChecked(checked)}
|
||||
disabled={isLoading}
|
||||
/>
|
||||
<Spacer />
|
||||
<TextField
|
||||
autoFocus="desktop"
|
||||
value={freeText}
|
||||
multiline
|
||||
translatableHintText={t`Please tell us more`}
|
||||
floatingLabelText={<Trans>Details</Trans>}
|
||||
floatingLabelFixed
|
||||
onChange={(e, value) => {
|
||||
setFreeText(value);
|
||||
}}
|
||||
onBlur={event => {
|
||||
setFreeText(event.currentTarget.value.trim());
|
||||
}}
|
||||
fullWidth
|
||||
disabled={isLoading}
|
||||
rows={4}
|
||||
/>
|
||||
</ColumnStackLayout>
|
||||
</Form>
|
||||
</ColumnStackLayout>
|
||||
)}
|
||||
</Dialog>
|
||||
)}
|
||||
</I18n>
|
||||
);
|
||||
};
|
||||
|
||||
export default CancelReasonDialog;
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user