mirror of
https://github.com/4ian/GDevelop.git
synced 2025-10-15 10:19:04 +00:00
Compare commits
75 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
70508292e4 | ||
![]() |
c899db1dba | ||
![]() |
2fb27f430e | ||
![]() |
6cd2400848 | ||
![]() |
fadccba757 | ||
![]() |
29a43514ce | ||
![]() |
e64ab94f76 | ||
![]() |
ed969d2909 | ||
![]() |
77bf67fdf0 | ||
![]() |
580c7a370c | ||
![]() |
266f0f2b6e | ||
![]() |
58af6aacb4 | ||
![]() |
1c4ee1c928 | ||
![]() |
0275476bec | ||
![]() |
3f0194acf0 | ||
![]() |
017d8b28c2 | ||
![]() |
4b518ba0fc | ||
![]() |
e4938b25b5 | ||
![]() |
c56ad2d277 | ||
![]() |
f069f9d942 | ||
![]() |
9f7c60a69e | ||
![]() |
774bf0db61 | ||
![]() |
ccd9c5c0ff | ||
![]() |
5b130a34e3 | ||
![]() |
3e6d147660 | ||
![]() |
433d85db94 | ||
![]() |
b75f707b30 | ||
![]() |
67799eb3eb | ||
![]() |
1173210386 | ||
![]() |
007cc48291 | ||
![]() |
12813c9ad9 | ||
![]() |
e503e34059 | ||
![]() |
4bf576a889 | ||
![]() |
eff1c1bcb6 | ||
![]() |
abce34f2b1 | ||
![]() |
07276d5e16 | ||
![]() |
1fdd8cc792 | ||
![]() |
79e40605d5 | ||
![]() |
fcc91e3fea | ||
![]() |
5c66623631 | ||
![]() |
5637642e1b | ||
![]() |
7e8b44af2e | ||
![]() |
0dd4650aae | ||
![]() |
c7cac31830 | ||
![]() |
56cb8581c4 | ||
![]() |
1993040b70 | ||
![]() |
883991081a | ||
![]() |
7d8afef1ad | ||
![]() |
8178595546 | ||
![]() |
a478068c64 | ||
![]() |
368da1b610 | ||
![]() |
4ee43202e9 | ||
![]() |
602fdf4bfd | ||
![]() |
6110acafcc | ||
![]() |
a3696ca9d1 | ||
![]() |
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",
|
||||
|
@@ -6,8 +6,6 @@
|
||||
|
||||
#include "GDCore/Extensions/Builtin/SpriteExtension/Animation.h"
|
||||
#include <vector>
|
||||
#include "GDCore/Extensions/Builtin/SpriteExtension/Direction.h"
|
||||
#include "GDCore/Extensions/Builtin/SpriteExtension/Sprite.h"
|
||||
#include "GDCore/String.h"
|
||||
|
||||
namespace gd {
|
||||
|
@@ -4,13 +4,11 @@
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef GDCORE_ANIMATION_H
|
||||
#define GDCORE_ANIMATION_H
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "GDCore/String.h"
|
||||
namespace gd {
|
||||
class Direction;
|
||||
}
|
||||
#include "GDCore/Extensions/Builtin/SpriteExtension/Direction.h"
|
||||
|
||||
namespace gd {
|
||||
|
||||
@@ -93,4 +91,3 @@ class GD_CORE_API Animation {
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
#endif // GDCORE_ANIMATION_H
|
||||
|
@@ -3,12 +3,12 @@
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#ifndef GDCORE_DIRECTION_H
|
||||
#define GDCORE_DIRECTION_H
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "GDCore/String.h"
|
||||
#include "GDCore/Extensions/Builtin/SpriteExtension/Sprite.h"
|
||||
namespace gd {
|
||||
class Sprite;
|
||||
class SerializerElement;
|
||||
}
|
||||
|
||||
@@ -142,4 +142,3 @@ class GD_CORE_API Direction {
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
#endif // GDCORE_DIRECTION_H
|
||||
|
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
|
||||
#include "GDCore/Extensions/Builtin/SpriteExtension/SpriteAnimationList.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "GDCore/CommonTools.h"
|
||||
#include "GDCore/Extensions/Builtin/SpriteExtension/Animation.h"
|
||||
#include "GDCore/Extensions/Builtin/SpriteExtension/Direction.h"
|
||||
#include "GDCore/IDE/Project/ArbitraryResourceWorker.h"
|
||||
#include "GDCore/Project/InitialInstance.h"
|
||||
#include "GDCore/Project/Layout.h"
|
||||
#include "GDCore/Project/Object.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/Project/PropertyDescriptor.h"
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
#include "GDCore/Tools/Localization.h"
|
||||
|
||||
namespace gd {
|
||||
|
||||
Animation SpriteAnimationList::badAnimation;
|
||||
|
||||
SpriteAnimationList::SpriteAnimationList()
|
||||
: adaptCollisionMaskAutomatically(true) {}
|
||||
|
||||
SpriteAnimationList::~SpriteAnimationList(){};
|
||||
|
||||
void SpriteAnimationList::UnserializeFrom(const gd::SerializerElement& element) {
|
||||
adaptCollisionMaskAutomatically =
|
||||
element.GetBoolAttribute("adaptCollisionMaskAutomatically", false);
|
||||
|
||||
RemoveAllAnimations();
|
||||
const gd::SerializerElement& animationsElement =
|
||||
element.GetChild("animations", 0, "Animations");
|
||||
animationsElement.ConsiderAsArrayOf("animation", "Animation");
|
||||
for (std::size_t i = 0; i < animationsElement.GetChildrenCount(); ++i) {
|
||||
const gd::SerializerElement& animationElement =
|
||||
animationsElement.GetChild(i);
|
||||
Animation newAnimation;
|
||||
|
||||
newAnimation.useMultipleDirections = animationElement.GetBoolAttribute(
|
||||
"useMultipleDirections", false, "typeNormal");
|
||||
newAnimation.SetName(animationElement.GetStringAttribute("name", ""));
|
||||
|
||||
// Compatibility with GD <= 3.3
|
||||
if (animationElement.HasChild("Direction")) {
|
||||
for (std::size_t j = 0;
|
||||
j < animationElement.GetChildrenCount("Direction");
|
||||
++j) {
|
||||
Direction direction;
|
||||
direction.UnserializeFrom(animationElement.GetChild("Direction", j));
|
||||
|
||||
newAnimation.SetDirectionsCount(newAnimation.GetDirectionsCount() + 1);
|
||||
newAnimation.SetDirection(direction,
|
||||
newAnimation.GetDirectionsCount() - 1);
|
||||
}
|
||||
}
|
||||
// End of compatibility code
|
||||
else {
|
||||
const gd::SerializerElement& directionsElement =
|
||||
animationElement.GetChild("directions");
|
||||
directionsElement.ConsiderAsArrayOf("direction");
|
||||
for (std::size_t j = 0; j < directionsElement.GetChildrenCount(); ++j) {
|
||||
Direction direction;
|
||||
direction.UnserializeFrom(directionsElement.GetChild(j));
|
||||
|
||||
newAnimation.SetDirectionsCount(newAnimation.GetDirectionsCount() + 1);
|
||||
newAnimation.SetDirection(direction,
|
||||
newAnimation.GetDirectionsCount() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
AddAnimation(newAnimation);
|
||||
}
|
||||
}
|
||||
|
||||
void SpriteAnimationList::SerializeTo(gd::SerializerElement& element) const {
|
||||
element.SetAttribute("adaptCollisionMaskAutomatically",
|
||||
adaptCollisionMaskAutomatically);
|
||||
|
||||
// Animations
|
||||
gd::SerializerElement& animationsElement = element.AddChild("animations");
|
||||
animationsElement.ConsiderAsArrayOf("animation");
|
||||
for (std::size_t k = 0; k < GetAnimationsCount(); k++) {
|
||||
gd::SerializerElement& animationElement =
|
||||
animationsElement.AddChild("animation");
|
||||
|
||||
animationElement.SetAttribute("useMultipleDirections",
|
||||
GetAnimation(k).useMultipleDirections);
|
||||
animationElement.SetAttribute("name", GetAnimation(k).GetName());
|
||||
|
||||
gd::SerializerElement& directionsElement =
|
||||
animationElement.AddChild("directions");
|
||||
directionsElement.ConsiderAsArrayOf("direction");
|
||||
for (std::size_t l = 0; l < GetAnimation(k).GetDirectionsCount(); l++) {
|
||||
GetAnimation(k).GetDirection(l).SerializeTo(
|
||||
directionsElement.AddChild("direction"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SpriteAnimationList::ExposeResources(gd::ArbitraryResourceWorker& worker) {
|
||||
for (std::size_t j = 0; j < GetAnimationsCount(); j++) {
|
||||
for (std::size_t k = 0; k < GetAnimation(j).GetDirectionsCount(); k++) {
|
||||
for (std::size_t l = 0;
|
||||
l < GetAnimation(j).GetDirection(k).GetSpritesCount();
|
||||
l++) {
|
||||
worker.ExposeImage(
|
||||
GetAnimation(j).GetDirection(k).GetSprite(l).GetImageName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const Animation& SpriteAnimationList::GetAnimation(std::size_t nb) const {
|
||||
if (nb >= animations.size()) return badAnimation;
|
||||
|
||||
return animations[nb];
|
||||
}
|
||||
|
||||
Animation& SpriteAnimationList::GetAnimation(std::size_t nb) {
|
||||
if (nb >= animations.size()) return badAnimation;
|
||||
|
||||
return animations[nb];
|
||||
}
|
||||
|
||||
void SpriteAnimationList::AddAnimation(const Animation& animation) {
|
||||
animations.push_back(animation);
|
||||
}
|
||||
|
||||
bool SpriteAnimationList::RemoveAnimation(std::size_t nb) {
|
||||
if (nb >= GetAnimationsCount()) return false;
|
||||
|
||||
animations.erase(animations.begin() + nb);
|
||||
return true;
|
||||
}
|
||||
|
||||
void SpriteAnimationList::SwapAnimations(std::size_t firstIndex,
|
||||
std::size_t secondIndex) {
|
||||
if (firstIndex < animations.size() && secondIndex < animations.size() &&
|
||||
firstIndex != secondIndex)
|
||||
std::swap(animations[firstIndex], animations[secondIndex]);
|
||||
}
|
||||
|
||||
void SpriteAnimationList::MoveAnimation(std::size_t oldIndex, std::size_t newIndex) {
|
||||
if (oldIndex >= animations.size() || newIndex >= animations.size()) return;
|
||||
|
||||
auto animation = animations[oldIndex];
|
||||
animations.erase(animations.begin() + oldIndex);
|
||||
animations.insert(animations.begin() + newIndex, animation);
|
||||
}
|
||||
|
||||
} // namespace gd
|
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GDCore/Extensions/Builtin/SpriteExtension/Animation.h"
|
||||
|
||||
namespace gd {
|
||||
class InitialInstance;
|
||||
class SerializerElement;
|
||||
class PropertyDescriptor;
|
||||
class ArbitraryResourceWorker;
|
||||
} // namespace gd
|
||||
|
||||
namespace gd {
|
||||
|
||||
/**
|
||||
* \brief A list of animations, containing directions with images and collision mask.
|
||||
*
|
||||
* It's used in the configuration of object that implements image-based animations.
|
||||
*
|
||||
* \see Animation
|
||||
* \see Direction
|
||||
* \see Sprite
|
||||
* \ingroup SpriteObjectExtension
|
||||
*/
|
||||
class GD_CORE_API SpriteAnimationList {
|
||||
public:
|
||||
SpriteAnimationList();
|
||||
virtual ~SpriteAnimationList();
|
||||
|
||||
void ExposeResources(gd::ArbitraryResourceWorker& worker);
|
||||
|
||||
/**
|
||||
* \brief Return the animation at the specified index.
|
||||
* If the index is out of bound, a "bad animation" object is returned.
|
||||
*/
|
||||
const Animation& GetAnimation(std::size_t nb) const;
|
||||
|
||||
/**
|
||||
* \brief Return the animation at the specified index.
|
||||
* If the index is out of bound, a "bad animation" object is returned.
|
||||
*/
|
||||
Animation& GetAnimation(std::size_t nb);
|
||||
|
||||
/**
|
||||
* \brief Return the number of animations this object has.
|
||||
*/
|
||||
std::size_t GetAnimationsCount() const { return animations.size(); };
|
||||
|
||||
/**
|
||||
* \brief Add an animation at the end of the existing ones.
|
||||
*/
|
||||
void AddAnimation(const Animation& animation);
|
||||
|
||||
/**
|
||||
* \brief Remove an animation.
|
||||
*/
|
||||
bool RemoveAnimation(std::size_t nb);
|
||||
|
||||
/**
|
||||
* \brief Remove all animations.
|
||||
*/
|
||||
void RemoveAllAnimations() { animations.clear(); }
|
||||
|
||||
/**
|
||||
* \brief Return true if the object hasn't any animation.
|
||||
*/
|
||||
bool HasNoAnimations() const { return animations.empty(); }
|
||||
|
||||
/**
|
||||
* \brief Swap the position of two animations
|
||||
*/
|
||||
void SwapAnimations(std::size_t firstIndex, std::size_t secondIndex);
|
||||
|
||||
/**
|
||||
* \brief Change the position of the specified animation
|
||||
*/
|
||||
void MoveAnimation(std::size_t oldIndex, std::size_t newIndex);
|
||||
|
||||
/**
|
||||
* \brief Return a read-only reference to the vector containing all the
|
||||
* animation of the object.
|
||||
*/
|
||||
const std::vector<Animation>& GetAllAnimations() const { return animations; }
|
||||
|
||||
/**
|
||||
* @brief Check if the collision mask adapts automatically to the animation.
|
||||
*/
|
||||
bool AdaptCollisionMaskAutomatically() const {
|
||||
return adaptCollisionMaskAutomatically;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set if the collision mask adapts automatically to the animation.
|
||||
*/
|
||||
void SetAdaptCollisionMaskAutomatically(bool enable) {
|
||||
adaptCollisionMaskAutomatically = enable;
|
||||
}
|
||||
|
||||
void UnserializeFrom(const gd::SerializerElement& element);
|
||||
void SerializeTo(gd::SerializerElement& element) const;
|
||||
|
||||
private:
|
||||
|
||||
mutable std::vector<Animation> animations;
|
||||
|
||||
static Animation badAnimation; //< Bad animation when an out of bound
|
||||
// animation is requested.
|
||||
bool adaptCollisionMaskAutomatically; ///< If set to true, the collision
|
||||
///< mask will be automatically
|
||||
///< adapted to the animation of the
|
||||
///< object.
|
||||
};
|
||||
|
||||
} // namespace gd
|
@@ -23,88 +23,20 @@
|
||||
|
||||
namespace gd {
|
||||
|
||||
Animation SpriteObject::badAnimation;
|
||||
|
||||
SpriteObject::SpriteObject()
|
||||
: updateIfNotVisible(false), adaptCollisionMaskAutomatically(true) {}
|
||||
: updateIfNotVisible(false) {}
|
||||
|
||||
SpriteObject::~SpriteObject(){};
|
||||
|
||||
void SpriteObject::DoUnserializeFrom(gd::Project& project,
|
||||
const gd::SerializerElement& element) {
|
||||
updateIfNotVisible = element.GetBoolAttribute("updateIfNotVisible", true);
|
||||
adaptCollisionMaskAutomatically =
|
||||
element.GetBoolAttribute("adaptCollisionMaskAutomatically", false);
|
||||
|
||||
RemoveAllAnimations();
|
||||
const gd::SerializerElement& animationsElement =
|
||||
element.GetChild("animations", 0, "Animations");
|
||||
animationsElement.ConsiderAsArrayOf("animation", "Animation");
|
||||
for (std::size_t i = 0; i < animationsElement.GetChildrenCount(); ++i) {
|
||||
const gd::SerializerElement& animationElement =
|
||||
animationsElement.GetChild(i);
|
||||
Animation newAnimation;
|
||||
|
||||
newAnimation.useMultipleDirections = animationElement.GetBoolAttribute(
|
||||
"useMultipleDirections", false, "typeNormal");
|
||||
newAnimation.SetName(animationElement.GetStringAttribute("name", ""));
|
||||
|
||||
// Compatibility with GD <= 3.3
|
||||
if (animationElement.HasChild("Direction")) {
|
||||
for (std::size_t j = 0;
|
||||
j < animationElement.GetChildrenCount("Direction");
|
||||
++j) {
|
||||
Direction direction;
|
||||
direction.UnserializeFrom(animationElement.GetChild("Direction", j));
|
||||
|
||||
newAnimation.SetDirectionsCount(newAnimation.GetDirectionsCount() + 1);
|
||||
newAnimation.SetDirection(direction,
|
||||
newAnimation.GetDirectionsCount() - 1);
|
||||
}
|
||||
}
|
||||
// End of compatibility code
|
||||
else {
|
||||
const gd::SerializerElement& directionsElement =
|
||||
animationElement.GetChild("directions");
|
||||
directionsElement.ConsiderAsArrayOf("direction");
|
||||
for (std::size_t j = 0; j < directionsElement.GetChildrenCount(); ++j) {
|
||||
Direction direction;
|
||||
direction.UnserializeFrom(directionsElement.GetChild(j));
|
||||
|
||||
newAnimation.SetDirectionsCount(newAnimation.GetDirectionsCount() + 1);
|
||||
newAnimation.SetDirection(direction,
|
||||
newAnimation.GetDirectionsCount() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
AddAnimation(newAnimation);
|
||||
}
|
||||
animations.UnserializeFrom(element);
|
||||
}
|
||||
|
||||
void SpriteObject::DoSerializeTo(gd::SerializerElement& element) const {
|
||||
element.SetAttribute("updateIfNotVisible", updateIfNotVisible);
|
||||
element.SetAttribute("adaptCollisionMaskAutomatically",
|
||||
adaptCollisionMaskAutomatically);
|
||||
|
||||
// Animations
|
||||
gd::SerializerElement& animationsElement = element.AddChild("animations");
|
||||
animationsElement.ConsiderAsArrayOf("animation");
|
||||
for (std::size_t k = 0; k < GetAnimationsCount(); k++) {
|
||||
gd::SerializerElement& animationElement =
|
||||
animationsElement.AddChild("animation");
|
||||
|
||||
animationElement.SetAttribute("useMultipleDirections",
|
||||
GetAnimation(k).useMultipleDirections);
|
||||
animationElement.SetAttribute("name", GetAnimation(k).GetName());
|
||||
|
||||
gd::SerializerElement& directionsElement =
|
||||
animationElement.AddChild("directions");
|
||||
directionsElement.ConsiderAsArrayOf("direction");
|
||||
for (std::size_t l = 0; l < GetAnimation(k).GetDirectionsCount(); l++) {
|
||||
GetAnimation(k).GetDirection(l).SerializeTo(
|
||||
directionsElement.AddChild("direction"));
|
||||
}
|
||||
}
|
||||
animations.SerializeTo(element);
|
||||
}
|
||||
|
||||
std::map<gd::String, gd::PropertyDescriptor> SpriteObject::GetProperties()
|
||||
@@ -127,16 +59,7 @@ bool SpriteObject::UpdateProperty(const gd::String& name,
|
||||
}
|
||||
|
||||
void SpriteObject::ExposeResources(gd::ArbitraryResourceWorker& worker) {
|
||||
for (std::size_t j = 0; j < GetAnimationsCount(); j++) {
|
||||
for (std::size_t k = 0; k < GetAnimation(j).GetDirectionsCount(); k++) {
|
||||
for (std::size_t l = 0;
|
||||
l < GetAnimation(j).GetDirection(k).GetSpritesCount();
|
||||
l++) {
|
||||
worker.ExposeImage(
|
||||
GetAnimation(j).GetDirection(k).GetSprite(l).GetImageName());
|
||||
}
|
||||
}
|
||||
}
|
||||
animations.ExposeResources(worker);
|
||||
}
|
||||
|
||||
std::map<gd::String, gd::PropertyDescriptor>
|
||||
@@ -168,42 +91,12 @@ bool SpriteObject::UpdateInitialInstanceProperty(
|
||||
return true;
|
||||
}
|
||||
|
||||
const Animation& SpriteObject::GetAnimation(std::size_t nb) const {
|
||||
if (nb >= animations.size()) return badAnimation;
|
||||
|
||||
return animations[nb];
|
||||
const SpriteAnimationList& SpriteObject::GetAnimations() const {
|
||||
return animations;
|
||||
}
|
||||
|
||||
Animation& SpriteObject::GetAnimation(std::size_t nb) {
|
||||
if (nb >= animations.size()) return badAnimation;
|
||||
|
||||
return animations[nb];
|
||||
}
|
||||
|
||||
void SpriteObject::AddAnimation(const Animation& animation) {
|
||||
animations.push_back(animation);
|
||||
}
|
||||
|
||||
bool SpriteObject::RemoveAnimation(std::size_t nb) {
|
||||
if (nb >= GetAnimationsCount()) return false;
|
||||
|
||||
animations.erase(animations.begin() + nb);
|
||||
return true;
|
||||
}
|
||||
|
||||
void SpriteObject::SwapAnimations(std::size_t firstIndex,
|
||||
std::size_t secondIndex) {
|
||||
if (firstIndex < animations.size() && secondIndex < animations.size() &&
|
||||
firstIndex != secondIndex)
|
||||
std::swap(animations[firstIndex], animations[secondIndex]);
|
||||
}
|
||||
|
||||
void SpriteObject::MoveAnimation(std::size_t oldIndex, std::size_t newIndex) {
|
||||
if (oldIndex >= animations.size() || newIndex >= animations.size()) return;
|
||||
|
||||
auto animation = animations[oldIndex];
|
||||
animations.erase(animations.begin() + oldIndex);
|
||||
animations.insert(animations.begin() + newIndex, animation);
|
||||
SpriteAnimationList& SpriteObject::GetAnimations() {
|
||||
return animations;
|
||||
}
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -4,18 +4,15 @@
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef GDCORE_SPRITEOBJECT_H
|
||||
#define GDCORE_SPRITEOBJECT_H
|
||||
#include "GDCore/Extensions/Builtin/SpriteExtension/Animation.h"
|
||||
#include "GDCore/Extensions/Builtin/SpriteExtension/Direction.h"
|
||||
#include "GDCore/Extensions/Builtin/SpriteExtension/Sprite.h"
|
||||
#pragma once
|
||||
|
||||
#include "GDCore/Extensions/Builtin/SpriteExtension/SpriteAnimationList.h"
|
||||
#include "GDCore/Project/Object.h"
|
||||
|
||||
namespace gd {
|
||||
class InitialInstance;
|
||||
class Object;
|
||||
class Layout;
|
||||
class Sprite;
|
||||
class Animation;
|
||||
class SerializerElement;
|
||||
class PropertyDescriptor;
|
||||
} // namespace gd
|
||||
@@ -59,76 +56,15 @@ class GD_CORE_API SpriteObject : public gd::ObjectConfiguration {
|
||||
gd::Project& project,
|
||||
gd::Layout& scene) override;
|
||||
|
||||
/** \name Animations
|
||||
* Methods related to animations management
|
||||
*/
|
||||
///@{
|
||||
/**
|
||||
* \brief Return the animation at the specified index.
|
||||
* If the index is out of bound, a "bad animation" object is returned.
|
||||
* \brief Return the animation configuration.
|
||||
*/
|
||||
const Animation& GetAnimation(std::size_t nb) const;
|
||||
const SpriteAnimationList& GetAnimations() const;
|
||||
|
||||
/**
|
||||
* \brief Return the animation at the specified index.
|
||||
* If the index is out of bound, a "bad animation" object is returned.
|
||||
* @brief Return the animation configuration.
|
||||
*/
|
||||
Animation& GetAnimation(std::size_t nb);
|
||||
|
||||
/**
|
||||
* \brief Return the number of animations this object has.
|
||||
*/
|
||||
std::size_t GetAnimationsCount() const { return animations.size(); };
|
||||
|
||||
/**
|
||||
* \brief Add an animation at the end of the existing ones.
|
||||
*/
|
||||
void AddAnimation(const Animation& animation);
|
||||
|
||||
/**
|
||||
* \brief Remove an animation.
|
||||
*/
|
||||
bool RemoveAnimation(std::size_t nb);
|
||||
|
||||
/**
|
||||
* \brief Remove all animations.
|
||||
*/
|
||||
void RemoveAllAnimations() { animations.clear(); }
|
||||
|
||||
/**
|
||||
* \brief Return true if the object hasn't any animation.
|
||||
*/
|
||||
bool HasNoAnimations() const { return animations.empty(); }
|
||||
|
||||
/**
|
||||
* \brief Swap the position of two animations
|
||||
*/
|
||||
void SwapAnimations(std::size_t firstIndex, std::size_t secondIndex);
|
||||
|
||||
/**
|
||||
* \brief Change the position of the specified animation
|
||||
*/
|
||||
void MoveAnimation(std::size_t oldIndex, std::size_t newIndex);
|
||||
|
||||
/**
|
||||
* \brief Return a read-only reference to the vector containing all the
|
||||
* animation of the object.
|
||||
*/
|
||||
const std::vector<Animation>& GetAllAnimations() const { return animations; }
|
||||
|
||||
/**
|
||||
* @brief Check if the collision mask adapts automatically to the animation.
|
||||
*/
|
||||
bool AdaptCollisionMaskAutomatically() const {
|
||||
return adaptCollisionMaskAutomatically;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set if the collision mask adapts automatically to the animation.
|
||||
*/
|
||||
void SetAdaptCollisionMaskAutomatically(bool enable) {
|
||||
adaptCollisionMaskAutomatically = enable;
|
||||
}
|
||||
SpriteAnimationList& GetAnimations();
|
||||
|
||||
/**
|
||||
* \brief Set if the object animation should be played even if the object is
|
||||
@@ -143,25 +79,17 @@ class GD_CORE_API SpriteObject : public gd::ObjectConfiguration {
|
||||
* is hidden or far from the camera (false by default).
|
||||
*/
|
||||
bool GetUpdateIfNotVisible() const { return updateIfNotVisible; }
|
||||
///@}
|
||||
|
||||
private:
|
||||
void DoUnserializeFrom(gd::Project& project,
|
||||
const gd::SerializerElement& element) override;
|
||||
void DoSerializeTo(gd::SerializerElement& element) const override;
|
||||
|
||||
mutable std::vector<Animation> animations;
|
||||
SpriteAnimationList animations;
|
||||
|
||||
bool updateIfNotVisible; ///< If set to true, ask the game engine to play
|
||||
///< object animation even if hidden or far from
|
||||
///< the screen.
|
||||
|
||||
static Animation badAnimation; //< Bad animation when an out of bound
|
||||
// animation is requested.
|
||||
bool adaptCollisionMaskAutomatically; ///< If set to true, the collision
|
||||
///< mask will be automatically
|
||||
///< adapted to the animation of the
|
||||
///< object.
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
#endif // GDCORE_SPRITEOBJECT_H
|
||||
|
@@ -86,8 +86,10 @@ class GD_CORE_API ExpressionValidator : public ExpressionParser2NodeWorker {
|
||||
void OnVisitOperatorNode(OperatorNode& node) override {
|
||||
ReportAnyError(node);
|
||||
|
||||
// The "required" type ("parentType") will be used when visiting the first operand.
|
||||
// Note that it may be refined thanks to this first operand (see later).
|
||||
node.leftHandSide->Visit(*this);
|
||||
const Type leftType = childType;
|
||||
const Type leftType = childType; // Store the type of the first operand.
|
||||
|
||||
if (leftType == Type::Number) {
|
||||
if (node.op == ' ') {
|
||||
@@ -120,15 +122,19 @@ class GD_CORE_API ExpressionValidator : public ExpressionParser2NodeWorker {
|
||||
node.rightHandSide->location);
|
||||
}
|
||||
|
||||
parentType = leftType;
|
||||
// The "required" type ("parentType") of the second operator is decided by:
|
||||
// - the parent type. Unless it can (`number|string`) or should (`unknown`) be refined, then:
|
||||
// - the first operand.
|
||||
parentType = ShouldTypeBeRefined(parentType) ? leftType : parentType;
|
||||
node.rightHandSide->Visit(*this);
|
||||
const Type rightType = childType;
|
||||
|
||||
// The type is decided by the first operand, unless it can (`number|string`)
|
||||
// or should (`unknown`) be refined, in which case we go for the right
|
||||
// operand (which got visited knowing the type of the first operand, so it's
|
||||
// The type of the overall operator ("childType") is decided by:
|
||||
// - the parent type. Unless it can (`number|string`) or should (`unknown`) be refined, then:
|
||||
// - the first operand. Unless it can (`number|string`) or should (`unknown`) be refined, then:
|
||||
// - the right operand (which got visited knowing the type of the first operand, so it's
|
||||
// equal or strictly more precise than the left operand).
|
||||
childType = (leftType == Type::Unknown || leftType == Type::NumberOrString) ? leftType : rightType;
|
||||
childType = ShouldTypeBeRefined(parentType) ? (ShouldTypeBeRefined(leftType) ? leftType : rightType) : parentType;
|
||||
}
|
||||
void OnVisitUnaryOperatorNode(UnaryOperatorNode& node) override {
|
||||
ReportAnyError(node);
|
||||
@@ -395,6 +401,10 @@ class GD_CORE_API ExpressionValidator : public ExpressionParser2NodeWorker {
|
||||
}
|
||||
}
|
||||
|
||||
static bool ShouldTypeBeRefined(Type type) {
|
||||
return (type == Type::Unknown || type == Type::NumberOrString);
|
||||
}
|
||||
|
||||
static Type StringToType(const gd::String &type);
|
||||
static const gd::String &TypeToString(Type type);
|
||||
static const gd::String unknownTypeString;
|
||||
|
@@ -13,12 +13,14 @@
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
#include "GDCore/Tools/Log.h"
|
||||
#include "GDCore/Project/CustomConfigurationHelper.h"
|
||||
#include "GDCore/Project/InitialInstance.h"
|
||||
|
||||
using namespace gd;
|
||||
|
||||
void CustomObjectConfiguration::Init(const gd::CustomObjectConfiguration& objectConfiguration) {
|
||||
project = objectConfiguration.project;
|
||||
objectContent = objectConfiguration.objectContent;
|
||||
animations = objectConfiguration.animations;
|
||||
|
||||
// There is no default copy for a map of unique_ptr like childObjectConfigurations.
|
||||
childObjectConfigurations.clear();
|
||||
@@ -88,23 +90,38 @@ bool CustomObjectConfiguration::UpdateProperty(const gd::String& propertyName,
|
||||
|
||||
std::map<gd::String, gd::PropertyDescriptor>
|
||||
CustomObjectConfiguration::GetInitialInstanceProperties(
|
||||
const gd::InitialInstance& instance,
|
||||
gd::Project& project,
|
||||
gd::Layout& scene) {
|
||||
return std::map<gd::String, gd::PropertyDescriptor>();
|
||||
const gd::InitialInstance &initialInstance, gd::Project &project,
|
||||
gd::Layout &scene) {
|
||||
std::map<gd::String, gd::PropertyDescriptor> properties;
|
||||
if (!animations.HasNoAnimations()) {
|
||||
properties["animation"] =
|
||||
gd::PropertyDescriptor(
|
||||
gd::String::From(initialInstance.GetRawDoubleProperty("animation")))
|
||||
.SetLabel(_("Animation"))
|
||||
.SetType("number");
|
||||
}
|
||||
return properties;
|
||||
}
|
||||
|
||||
bool CustomObjectConfiguration::UpdateInitialInstanceProperty(
|
||||
gd::InitialInstance& instance,
|
||||
const gd::String& name,
|
||||
const gd::String& value,
|
||||
gd::Project& project,
|
||||
gd::Layout& scene) {
|
||||
return false;
|
||||
gd::InitialInstance &initialInstance, const gd::String &name,
|
||||
const gd::String &value, gd::Project &project, gd::Layout &scene) {
|
||||
if (name == "animation") {
|
||||
initialInstance.SetRawDoubleProperty(
|
||||
"animation", std::max(0, value.empty() ? 0 : value.To<int>()));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CustomObjectConfiguration::DoSerializeTo(SerializerElement& element) const {
|
||||
element.AddChild("content") = objectContent;
|
||||
|
||||
if (!animations.HasNoAnimations()) {
|
||||
auto &animatableElement = element.AddChild("animatable");
|
||||
animations.SerializeTo(animatableElement);
|
||||
}
|
||||
|
||||
auto &childrenContentElement = element.AddChild("childrenContent");
|
||||
for (auto &pair : childObjectConfigurations) {
|
||||
auto &childName = pair.first;
|
||||
@@ -116,6 +133,12 @@ void CustomObjectConfiguration::DoSerializeTo(SerializerElement& element) const
|
||||
void CustomObjectConfiguration::DoUnserializeFrom(Project& project,
|
||||
const SerializerElement& element) {
|
||||
objectContent = element.GetChild("content");
|
||||
|
||||
if (element.HasChild("animatable")) {
|
||||
auto &animatableElement = element.GetChild("animatable");
|
||||
animations.UnserializeFrom(animatableElement);
|
||||
}
|
||||
|
||||
auto &childrenContentElement = element.GetChild("childrenContent");
|
||||
for (auto &pair : childrenContentElement.GetAllChildren()) {
|
||||
auto &childName = pair.first;
|
||||
@@ -126,6 +149,8 @@ void CustomObjectConfiguration::DoUnserializeFrom(Project& project,
|
||||
}
|
||||
|
||||
void CustomObjectConfiguration::ExposeResources(gd::ArbitraryResourceWorker& worker) {
|
||||
animations.ExposeResources(worker);
|
||||
|
||||
std::map<gd::String, gd::PropertyDescriptor> properties = GetProperties();
|
||||
|
||||
for (auto& property : properties) {
|
||||
@@ -178,3 +203,11 @@ void CustomObjectConfiguration::ExposeResources(gd::ArbitraryResourceWorker& wor
|
||||
configuration.ExposeResources(worker);
|
||||
}
|
||||
}
|
||||
|
||||
const SpriteAnimationList& CustomObjectConfiguration::GetAnimations() const {
|
||||
return animations;
|
||||
}
|
||||
|
||||
SpriteAnimationList& CustomObjectConfiguration::GetAnimations() {
|
||||
return animations;
|
||||
}
|
||||
|
@@ -3,8 +3,7 @@
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#ifndef GDCORE_CUSTOMOBJECTCONFIGURATION_H
|
||||
#define GDCORE_CUSTOMOBJECTCONFIGURATION_H
|
||||
#pragma once
|
||||
|
||||
#include "GDCore/Project/ObjectConfiguration.h"
|
||||
|
||||
@@ -16,7 +15,7 @@
|
||||
#include "GDCore/Project/PropertyDescriptor.h"
|
||||
#include "GDCore/Serialization/Serializer.h"
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
|
||||
#include "GDCore/Extensions/Builtin/SpriteExtension/SpriteAnimationList.h"
|
||||
|
||||
using namespace gd;
|
||||
|
||||
@@ -72,7 +71,17 @@ class CustomObjectConfiguration : public gd::ObjectConfiguration {
|
||||
|
||||
gd::ObjectConfiguration &GetChildObjectConfiguration(const gd::String& objectName);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* \brief Return the animation configuration for Animatable custom objects.
|
||||
*/
|
||||
const SpriteAnimationList& GetAnimations() const;
|
||||
|
||||
/**
|
||||
* @brief Return the animation configuration for Animatable custom objects.
|
||||
*/
|
||||
SpriteAnimationList& GetAnimations();
|
||||
|
||||
protected:
|
||||
void DoSerializeTo(SerializerElement& element) const override;
|
||||
void DoUnserializeFrom(Project& project, const SerializerElement& element) override;
|
||||
|
||||
@@ -84,6 +93,8 @@ class CustomObjectConfiguration : public gd::ObjectConfiguration {
|
||||
|
||||
static gd::ObjectConfiguration badObjectConfiguration;
|
||||
|
||||
SpriteAnimationList animations;
|
||||
|
||||
/**
|
||||
* Initialize configuration using another configuration. Used by copy-ctor
|
||||
* and assign-op.
|
||||
@@ -95,6 +106,5 @@ class CustomObjectConfiguration : public gd::ObjectConfiguration {
|
||||
*/
|
||||
void Init(const gd::CustomObjectConfiguration& object);
|
||||
};
|
||||
} // namespace gd
|
||||
|
||||
#endif // GDCORE_CUSTOMOBJECTCONFIGURATION_H
|
||||
} // namespace gd
|
||||
|
@@ -14,7 +14,9 @@ EventsBasedObject::EventsBasedObject()
|
||||
"MyObject",
|
||||
gd::EventsFunctionsContainer::FunctionOwner::Object),
|
||||
ObjectsContainer(),
|
||||
isRenderedIn3D(false) {
|
||||
isRenderedIn3D(false),
|
||||
isAnimatable(false),
|
||||
isTextContainer(false) {
|
||||
}
|
||||
|
||||
EventsBasedObject::~EventsBasedObject() {}
|
||||
@@ -31,6 +33,12 @@ void EventsBasedObject::SerializeTo(SerializerElement& element) const {
|
||||
if (isRenderedIn3D) {
|
||||
element.SetBoolAttribute("is3D", true);
|
||||
}
|
||||
if (isAnimatable) {
|
||||
element.SetBoolAttribute("isAnimatable", true);
|
||||
}
|
||||
if (isTextContainer) {
|
||||
element.SetBoolAttribute("isTextContainer", true);
|
||||
}
|
||||
|
||||
AbstractEventsBasedEntity::SerializeTo(element);
|
||||
SerializeObjectsTo(element.AddChild("objects"));
|
||||
@@ -41,6 +49,8 @@ void EventsBasedObject::UnserializeFrom(gd::Project& project,
|
||||
const SerializerElement& element) {
|
||||
defaultName = element.GetStringAttribute("defaultName");
|
||||
isRenderedIn3D = element.GetBoolAttribute("is3D", false);
|
||||
isAnimatable = element.GetBoolAttribute("isAnimatable", false);
|
||||
isTextContainer = element.GetBoolAttribute("isTextContainer", false);
|
||||
|
||||
AbstractEventsBasedEntity::UnserializeFrom(project, element);
|
||||
UnserializeObjectsFrom(project, element.GetChild("objects"));
|
||||
|
@@ -85,6 +85,32 @@ class GD_CORE_API EventsBasedObject: public AbstractEventsBasedEntity, public Ob
|
||||
*/
|
||||
bool IsRenderedIn3D() const { return isRenderedIn3D; }
|
||||
|
||||
/**
|
||||
* \brief Declare an Animatable capability.
|
||||
*/
|
||||
EventsBasedObject& MarkAsAnimatable(bool isAnimatable_) {
|
||||
isAnimatable = isAnimatable_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return true if the object needs an Animatable capability.
|
||||
*/
|
||||
bool IsAnimatable() const { return isAnimatable; }
|
||||
|
||||
/**
|
||||
* \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 +119,8 @@ class GD_CORE_API EventsBasedObject: public AbstractEventsBasedEntity, public Ob
|
||||
private:
|
||||
gd::String defaultName;
|
||||
bool isRenderedIn3D;
|
||||
bool isAnimatable;
|
||||
bool isTextContainer;
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -15,7 +15,7 @@
|
||||
|
||||
namespace gd {
|
||||
|
||||
gd::String* InitialInstance::badStringProperyValue = NULL;
|
||||
gd::String* InitialInstance::badStringPropertyValue = NULL;
|
||||
|
||||
InitialInstance::InitialInstance()
|
||||
: objectName(""),
|
||||
@@ -34,6 +34,7 @@ InitialInstance::InitialInstance()
|
||||
depth(0),
|
||||
locked(false),
|
||||
sealed(false),
|
||||
keepRatio(true),
|
||||
persistentUuid(UUID::MakeUuid4()) {}
|
||||
|
||||
void InitialInstance::UnserializeFrom(const SerializerElement& element) {
|
||||
@@ -58,6 +59,7 @@ void InitialInstance::UnserializeFrom(const SerializerElement& element) {
|
||||
SetLayer(element.GetStringAttribute("layer"));
|
||||
SetLocked(element.GetBoolAttribute("locked", false));
|
||||
SetSealed(element.GetBoolAttribute("sealed", false));
|
||||
SetShouldKeepRatio(element.GetBoolAttribute("keepRatio", false));
|
||||
|
||||
persistentUuid = element.GetStringAttribute("persistentUuid");
|
||||
if (persistentUuid.empty()) ResetPersistentUuid();
|
||||
@@ -120,6 +122,7 @@ void InitialInstance::SerializeTo(SerializerElement& element) const {
|
||||
if (HasCustomDepth()) element.SetAttribute("depth", GetCustomDepth());
|
||||
if (IsLocked()) element.SetAttribute("locked", IsLocked());
|
||||
if (IsSealed()) element.SetAttribute("sealed", IsSealed());
|
||||
if (ShouldKeepRatio()) element.SetAttribute("keepRatio", ShouldKeepRatio());
|
||||
|
||||
if (persistentUuid.empty()) persistentUuid = UUID::MakeUuid4();
|
||||
element.SetStringAttribute("persistentUuid", persistentUuid);
|
||||
@@ -188,10 +191,10 @@ double InitialInstance::GetRawDoubleProperty(const gd::String& name) const {
|
||||
|
||||
const gd::String& InitialInstance::GetRawStringProperty(
|
||||
const gd::String& name) const {
|
||||
if (!badStringProperyValue) badStringProperyValue = new gd::String("");
|
||||
if (!badStringPropertyValue) badStringPropertyValue = new gd::String("");
|
||||
|
||||
const auto& it = stringProperties.find(name);
|
||||
return it != stringProperties.end() ? it->second : *badStringProperyValue;
|
||||
return it != stringProperties.end() ? it->second : *badStringPropertyValue;
|
||||
}
|
||||
|
||||
void InitialInstance::SetRawDoubleProperty(const gd::String& name,
|
||||
|
@@ -206,6 +206,17 @@ class GD_CORE_API InitialInstance {
|
||||
*/
|
||||
void SetSealed(bool enable = true) { sealed = enable; }
|
||||
|
||||
/**
|
||||
* \brief Return true if the dimensions (width, height and depth) should keep
|
||||
* the same ratio.
|
||||
*/
|
||||
bool ShouldKeepRatio() const { return keepRatio; };
|
||||
|
||||
/**
|
||||
* \brief Define if instance's dimensions should keep the same ratio.
|
||||
*/
|
||||
void SetShouldKeepRatio(bool enable = true) { keepRatio = enable; }
|
||||
|
||||
///@}
|
||||
|
||||
/** \name Variable management
|
||||
@@ -340,11 +351,13 @@ class GD_CORE_API InitialInstance {
|
||||
gd::VariablesContainer initialVariables; ///< Instance specific variables
|
||||
bool locked; ///< True if the instance is locked
|
||||
bool sealed; ///< True if the instance is sealed
|
||||
bool keepRatio; ///< True if the instance's dimensions
|
||||
/// should keep the same ratio.
|
||||
mutable gd::String persistentUuid; ///< A persistent random version 4 UUID,
|
||||
///< useful for hot reloading.
|
||||
/// useful for hot reloading.
|
||||
|
||||
static gd::String*
|
||||
badStringProperyValue; ///< Empty string returned by GetRawStringProperty
|
||||
badStringPropertyValue; ///< Empty string returned by GetRawStringProperty
|
||||
};
|
||||
|
||||
} // 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);
|
||||
}
|
||||
|
@@ -91,7 +91,7 @@ TEST_CASE("ArbitraryResourceWorker", "[common][resources]") {
|
||||
sprite.SetImageName("res1");
|
||||
anim.SetDirectionsCount(1);
|
||||
anim.GetDirection(0).AddSprite(sprite);
|
||||
spriteConfiguration.AddAnimation(anim);
|
||||
spriteConfiguration.GetAnimations().AddAnimation(anim);
|
||||
|
||||
gd::Object obj("myObject", "", spriteConfiguration.Clone());
|
||||
project.InsertObject(obj, 0);
|
||||
@@ -138,7 +138,7 @@ TEST_CASE("ArbitraryResourceWorker", "[common][resources]") {
|
||||
sprite.SetImageName("res1");
|
||||
anim.SetDirectionsCount(1);
|
||||
anim.GetDirection(0).AddSprite(sprite);
|
||||
spriteConfiguration.AddAnimation(anim);
|
||||
spriteConfiguration.GetAnimations().AddAnimation(anim);
|
||||
|
||||
gd::Object obj("myObject", "", spriteConfiguration.Clone());
|
||||
layout.InsertObject(obj, 0);
|
||||
@@ -437,7 +437,7 @@ TEST_CASE("ArbitraryResourceWorker", "[common][resources]") {
|
||||
sprite.SetImageName("res1");
|
||||
anim.SetDirectionsCount(1);
|
||||
anim.GetDirection(0).AddSprite(sprite);
|
||||
spriteConfiguration.AddAnimation(anim);
|
||||
spriteConfiguration.GetAnimations().AddAnimation(anim);
|
||||
|
||||
gd::Object obj("myObject", "", spriteConfiguration.Clone());
|
||||
layout.InsertObject(obj, 0);
|
||||
|
@@ -30,6 +30,21 @@ TEST_CASE("ExpressionCodeGenerator", "[common][events]") {
|
||||
layout1.GetVariables().InsertNew("MySceneBooleanVariable").SetBool(true);
|
||||
layout1.GetVariables().InsertNew("MySceneStructureVariable").GetChild("MyChild");
|
||||
layout1.GetVariables().InsertNew("MySceneStructureVariable2").GetChild("MyChild");
|
||||
layout1.GetVariables().InsertNew("MySceneEmptyArrayVariable").CastTo(gd::Variable::Type::Array);
|
||||
{
|
||||
auto& variable = layout1.GetVariables().InsertNew("MySceneNumberArrayVariable");
|
||||
variable.CastTo(gd::Variable::Type::Array);
|
||||
variable.PushNew().SetValue(1);
|
||||
variable.PushNew().SetValue(2);
|
||||
variable.PushNew().SetValue(3);
|
||||
}
|
||||
{
|
||||
auto& variable = layout1.GetVariables().InsertNew("MySceneStringArrayVariable");
|
||||
variable.CastTo(gd::Variable::Type::Array);
|
||||
variable.PushNew().SetString("1");
|
||||
variable.PushNew().SetString("2");
|
||||
variable.PushNew().SetString("3");
|
||||
}
|
||||
|
||||
auto &mySpriteObject = layout1.InsertNewObject(project, "MyExtension::Sprite", "MySpriteObject", 0);
|
||||
mySpriteObject.GetVariables().InsertNew("MyNumberVariable").SetValue(123);
|
||||
@@ -1295,6 +1310,221 @@ TEST_CASE("ExpressionCodeGenerator", "[common][events]") {
|
||||
REQUIRE(output == "getVariableForObject(MySpriteObject, MyOtherSpriteObject).getChild(\"Child\").getChild(\"Grandchild\")");
|
||||
}
|
||||
}
|
||||
SECTION("Type conversions (valid operators with variables having different types than the expression)") {
|
||||
SECTION("Expression/parent type is 'string'") {
|
||||
{
|
||||
auto node =
|
||||
parser.ParseExpression("\"You have \" + MySceneVariable + \" points\"");
|
||||
gd::ExpressionCodeGenerator expressionCodeGenerator("string",
|
||||
"",
|
||||
codeGenerator,
|
||||
context);
|
||||
|
||||
REQUIRE(node);
|
||||
node->Visit(expressionCodeGenerator);
|
||||
REQUIRE(expressionCodeGenerator.GetOutput() == "\"You have \" + getLayoutVariable(MySceneVariable).getAsString() + \" points\"");
|
||||
}
|
||||
{
|
||||
auto node =
|
||||
parser.ParseExpression("MySceneVariable + MySceneStringVariable");
|
||||
gd::ExpressionCodeGenerator expressionCodeGenerator("string",
|
||||
"",
|
||||
codeGenerator,
|
||||
context);
|
||||
|
||||
REQUIRE(node);
|
||||
node->Visit(expressionCodeGenerator);
|
||||
REQUIRE(expressionCodeGenerator.GetOutput() == "getLayoutVariable(MySceneVariable).getAsString() + getLayoutVariable(MySceneStringVariable).getAsString()");
|
||||
}
|
||||
}
|
||||
SECTION("Expression/parent type is 'string' (with an unknown variable)") {
|
||||
{
|
||||
auto node =
|
||||
parser.ParseExpression("\"You have \" + MySceneStructureVariable.MyChild.CantKnownTheTypeSoStayGeneric + \" points\"");
|
||||
gd::ExpressionCodeGenerator expressionCodeGenerator("string",
|
||||
"",
|
||||
codeGenerator,
|
||||
context);
|
||||
|
||||
REQUIRE(node);
|
||||
node->Visit(expressionCodeGenerator);
|
||||
REQUIRE(expressionCodeGenerator.GetOutput() == "\"You have \" + getLayoutVariable(MySceneStructureVariable).getChild(\"MyChild\").getChild(\"CantKnownTheTypeSoStayGeneric\").getAsString() + \" points\"");
|
||||
}
|
||||
}
|
||||
SECTION("Expression/parent type is 'string' (2 number variables)") {
|
||||
{
|
||||
auto node =
|
||||
parser.ParseExpression("MySceneVariable + MySceneVariable2 + \"world\"");
|
||||
gd::ExpressionCodeGenerator expressionCodeGenerator("string",
|
||||
"",
|
||||
codeGenerator,
|
||||
context);
|
||||
|
||||
REQUIRE(node);
|
||||
node->Visit(expressionCodeGenerator);
|
||||
REQUIRE(expressionCodeGenerator.GetOutput() == "getLayoutVariable(MySceneVariable).getAsString() + getLayoutVariable(MySceneVariable2).getAsString() + \"world\"");
|
||||
}
|
||||
{
|
||||
auto node =
|
||||
parser.ParseExpression("MySceneVariable + MySceneVariable2 + MySceneStringVariable");
|
||||
gd::ExpressionCodeGenerator expressionCodeGenerator("string",
|
||||
"",
|
||||
codeGenerator,
|
||||
context);
|
||||
|
||||
REQUIRE(node);
|
||||
node->Visit(expressionCodeGenerator);
|
||||
REQUIRE(expressionCodeGenerator.GetOutput() == "getLayoutVariable(MySceneVariable).getAsString() + getLayoutVariable(MySceneVariable2).getAsString() + getLayoutVariable(MySceneStringVariable).getAsString()");
|
||||
}
|
||||
}
|
||||
SECTION("Expression/parent type is 'string' (array variable)") {
|
||||
{
|
||||
auto node =
|
||||
parser.ParseExpression("\"hello\" + MySceneNumberArrayVariable[2] + \"world\"");
|
||||
gd::ExpressionCodeGenerator expressionCodeGenerator("string",
|
||||
"",
|
||||
codeGenerator,
|
||||
context);
|
||||
|
||||
REQUIRE(node);
|
||||
node->Visit(expressionCodeGenerator);
|
||||
REQUIRE(expressionCodeGenerator.GetOutput() == "\"hello\" + getLayoutVariable(MySceneNumberArrayVariable).getChild(2).getAsString() + \"world\"");
|
||||
}
|
||||
{
|
||||
auto node =
|
||||
parser.ParseExpression("\"hello\" + MySceneEmptyArrayVariable[2] + \"world\"");
|
||||
gd::ExpressionCodeGenerator expressionCodeGenerator("string",
|
||||
"",
|
||||
codeGenerator,
|
||||
context);
|
||||
|
||||
REQUIRE(node);
|
||||
node->Visit(expressionCodeGenerator);
|
||||
REQUIRE(expressionCodeGenerator.GetOutput() == "\"hello\" + getLayoutVariable(MySceneEmptyArrayVariable).getChild(2).getAsString() + \"world\"");
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Expression/parent type is 'number'") {
|
||||
{
|
||||
auto node =
|
||||
parser.ParseExpression("123 + MySceneVariable + 456");
|
||||
gd::ExpressionCodeGenerator expressionCodeGenerator("number",
|
||||
"",
|
||||
codeGenerator,
|
||||
context);
|
||||
|
||||
REQUIRE(node);
|
||||
node->Visit(expressionCodeGenerator);
|
||||
REQUIRE(expressionCodeGenerator.GetOutput() == "123 + getLayoutVariable(MySceneVariable).getAsNumber() + 456");
|
||||
}
|
||||
{
|
||||
auto node =
|
||||
parser.ParseExpression("MySceneStringVariable + MySceneVariable");
|
||||
gd::ExpressionCodeGenerator expressionCodeGenerator("number",
|
||||
"",
|
||||
codeGenerator,
|
||||
context);
|
||||
|
||||
REQUIRE(node);
|
||||
node->Visit(expressionCodeGenerator);
|
||||
REQUIRE(expressionCodeGenerator.GetOutput() == "getLayoutVariable(MySceneStringVariable).getAsNumber() + getLayoutVariable(MySceneVariable).getAsNumber()");
|
||||
}
|
||||
}
|
||||
SECTION("Expression/parent type is 'string' (with an unknown variable)") {
|
||||
{
|
||||
auto node =
|
||||
parser.ParseExpression("123 + MySceneStructureVariable.MyChild.CantKnownTheTypeSoStayGeneric + 456");
|
||||
gd::ExpressionCodeGenerator expressionCodeGenerator("number",
|
||||
"",
|
||||
codeGenerator,
|
||||
context);
|
||||
|
||||
REQUIRE(node);
|
||||
node->Visit(expressionCodeGenerator);
|
||||
REQUIRE(expressionCodeGenerator.GetOutput() == "123 + getLayoutVariable(MySceneStructureVariable).getChild(\"MyChild\").getChild(\"CantKnownTheTypeSoStayGeneric\").getAsNumber() + 456");
|
||||
}
|
||||
}
|
||||
SECTION("Expression/parent type is 'number' (2 string variables)") {
|
||||
{
|
||||
auto node =
|
||||
parser.ParseExpression("MySceneStringVariable + MySceneStringVariable + 456");
|
||||
gd::ExpressionCodeGenerator expressionCodeGenerator("number",
|
||||
"",
|
||||
codeGenerator,
|
||||
context);
|
||||
|
||||
REQUIRE(node);
|
||||
node->Visit(expressionCodeGenerator);
|
||||
REQUIRE(expressionCodeGenerator.GetOutput() == "getLayoutVariable(MySceneStringVariable).getAsNumber() + getLayoutVariable(MySceneStringVariable).getAsNumber() + 456");
|
||||
}
|
||||
{
|
||||
auto node =
|
||||
parser.ParseExpression("MySceneStringVariable + MySceneStringVariable + MySceneVariable");
|
||||
gd::ExpressionCodeGenerator expressionCodeGenerator("number",
|
||||
"",
|
||||
codeGenerator,
|
||||
context);
|
||||
|
||||
REQUIRE(node);
|
||||
node->Visit(expressionCodeGenerator);
|
||||
REQUIRE(expressionCodeGenerator.GetOutput() == "getLayoutVariable(MySceneStringVariable).getAsNumber() + getLayoutVariable(MySceneStringVariable).getAsNumber() + getLayoutVariable(MySceneVariable).getAsNumber()");
|
||||
}
|
||||
}
|
||||
SECTION("Expression/parent type is 'number' (array variable)") {
|
||||
{
|
||||
auto node =
|
||||
parser.ParseExpression("123 + MySceneNumberArrayVariable[2] + 456");
|
||||
gd::ExpressionCodeGenerator expressionCodeGenerator("number",
|
||||
"",
|
||||
codeGenerator,
|
||||
context);
|
||||
|
||||
REQUIRE(node);
|
||||
node->Visit(expressionCodeGenerator);
|
||||
REQUIRE(expressionCodeGenerator.GetOutput() == "123 + getLayoutVariable(MySceneNumberArrayVariable).getChild(2).getAsNumber() + 456");
|
||||
}
|
||||
{
|
||||
auto node =
|
||||
parser.ParseExpression("123 + MySceneEmptyArrayVariable[2] + 456");
|
||||
gd::ExpressionCodeGenerator expressionCodeGenerator("number",
|
||||
"",
|
||||
codeGenerator,
|
||||
context);
|
||||
|
||||
REQUIRE(node);
|
||||
node->Visit(expressionCodeGenerator);
|
||||
REQUIRE(expressionCodeGenerator.GetOutput() == "123 + getLayoutVariable(MySceneEmptyArrayVariable).getChild(2).getAsNumber() + 456");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SECTION("Multiple type conversions in sub expressions or same expression") {
|
||||
{
|
||||
auto node =
|
||||
parser.ParseExpression("\"hello\" + MySceneNumberArrayVariable[2 + MySceneStringVariable] + \"world\" + MySceneVariable + \"world 2\"");
|
||||
gd::ExpressionCodeGenerator expressionCodeGenerator("string",
|
||||
"",
|
||||
codeGenerator,
|
||||
context);
|
||||
|
||||
REQUIRE(node);
|
||||
node->Visit(expressionCodeGenerator);
|
||||
REQUIRE(expressionCodeGenerator.GetOutput() == "\"hello\" + getLayoutVariable(MySceneNumberArrayVariable).getChild(2 + getLayoutVariable(MySceneStringVariable).getAsNumber()).getAsString() + \"world\" + getLayoutVariable(MySceneVariable).getAsString() + \"world 2\"");
|
||||
}
|
||||
{
|
||||
auto node =
|
||||
parser.ParseExpression("\"hello\" + MySceneNumberArrayVariable[\"foo\" + MySceneVariable + \"bar\"] + \"world\" + MySceneVariable + \"world 2\"");
|
||||
gd::ExpressionCodeGenerator expressionCodeGenerator("string",
|
||||
"",
|
||||
codeGenerator,
|
||||
context);
|
||||
|
||||
REQUIRE(node);
|
||||
node->Visit(expressionCodeGenerator);
|
||||
REQUIRE(expressionCodeGenerator.GetOutput() == "\"hello\" + getLayoutVariable(MySceneNumberArrayVariable).getChild(\"foo\" + getLayoutVariable(MySceneVariable).getAsString() + \"bar\").getAsString() + \"world\" + getLayoutVariable(MySceneVariable).getAsString() + \"world 2\"");
|
||||
}
|
||||
}
|
||||
}
|
||||
SECTION("Mixed test (1)") {
|
||||
{
|
||||
auto node = parser.ParseExpression("-+-MyExtension::MouseX(,)");
|
||||
|
@@ -2954,6 +2954,238 @@ TEST_CASE("ExpressionParser2", "[common][events]") {
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Valid operators with variables having different types than the expression") {
|
||||
SECTION("Expression/parent type is 'string'") {
|
||||
// A trivial test (everything is a string).
|
||||
{
|
||||
auto node = parser.ParseExpression("\"You have \" + MySceneStringVariable + \" points\"");
|
||||
REQUIRE(node != nullptr);
|
||||
|
||||
gd::ExpressionValidator validator(platform, projectScopedContainers, "string");
|
||||
node->Visit(validator);
|
||||
REQUIRE(validator.GetFatalErrors().size() == 0);
|
||||
}
|
||||
// A string concatenated with a number variable (will have to be casted to a string in code generation)
|
||||
{
|
||||
auto node = parser.ParseExpression("\"You have \" + MySceneNumberVariable");
|
||||
REQUIRE(node != nullptr);
|
||||
|
||||
gd::ExpressionValidator validator(platform, projectScopedContainers, "string");
|
||||
node->Visit(validator);
|
||||
|
||||
REQUIRE(validator.GetFatalErrors().size() == 0);
|
||||
}
|
||||
// A string concatenated with a number variable (will have to be casted to a string in code generation)
|
||||
// and then with a string again.
|
||||
{
|
||||
auto node = parser.ParseExpression("\"You have \" + MySceneNumberVariable + \" points\"");
|
||||
REQUIRE(node != nullptr);
|
||||
|
||||
gd::ExpressionValidator validator(platform, projectScopedContainers, "string");
|
||||
node->Visit(validator);
|
||||
|
||||
REQUIRE(validator.GetFatalErrors().size() == 0);
|
||||
}
|
||||
// A string concatenated with an unknown variable (will have to be casted to a string in code generation)
|
||||
// and then with a string again.
|
||||
{
|
||||
auto node = parser.ParseExpression("\"You have \" + MySceneStructureVariable.MyChild.CantKnownTheTypeSoStayGeneric + \" points\"");
|
||||
REQUIRE(node != nullptr);
|
||||
|
||||
gd::ExpressionValidator validator(platform, projectScopedContainers, "string");
|
||||
node->Visit(validator);
|
||||
|
||||
REQUIRE(validator.GetFatalErrors().size() == 0);
|
||||
}
|
||||
}
|
||||
SECTION("Expression/parent type is 'number'") {
|
||||
// A trivial test (everything is a string).
|
||||
{
|
||||
auto node = parser.ParseExpression("123 + MySceneNumberVariable + 456");
|
||||
REQUIRE(node != nullptr);
|
||||
|
||||
gd::ExpressionValidator validator(platform, projectScopedContainers, "number");
|
||||
node->Visit(validator);
|
||||
REQUIRE(validator.GetFatalErrors().size() == 0);
|
||||
}
|
||||
// A number concatenated with a string variable (will have to be casted to a number in code generation)
|
||||
{
|
||||
auto node = parser.ParseExpression("123 + MySceneStringVariable");
|
||||
REQUIRE(node != nullptr);
|
||||
|
||||
gd::ExpressionValidator validator(platform, projectScopedContainers, "number");
|
||||
node->Visit(validator);
|
||||
|
||||
REQUIRE(validator.GetFatalErrors().size() == 0);
|
||||
}
|
||||
// A number concatenated with a string variable (will have to be casted to a number in code generation)
|
||||
// and then with a number again.
|
||||
{
|
||||
auto node = parser.ParseExpression("123 + MySceneStringVariable + 456");
|
||||
REQUIRE(node != nullptr);
|
||||
|
||||
gd::ExpressionValidator validator(platform, projectScopedContainers, "number");
|
||||
node->Visit(validator);
|
||||
|
||||
REQUIRE(validator.GetFatalErrors().size() == 0);
|
||||
}
|
||||
// A number concatenated with an unknown variable (will have to be casted to a number in code generation)
|
||||
// and then with a number again.
|
||||
{
|
||||
auto node = parser.ParseExpression("123 + MySceneStructureVariable.MyChild.CantKnownTheTypeSoStayGeneric + 456");
|
||||
REQUIRE(node != nullptr);
|
||||
|
||||
gd::ExpressionValidator validator(platform, projectScopedContainers, "number");
|
||||
node->Visit(validator);
|
||||
|
||||
REQUIRE(validator.GetFatalErrors().size() == 0);
|
||||
}
|
||||
}
|
||||
SECTION("Expression/parent type is 'number|string'") {
|
||||
SECTION("Expression/parent inferred type is 'string'") {
|
||||
// A trivial test (everything is a string).
|
||||
{
|
||||
auto node = parser.ParseExpression("\"You have \" + MySceneStringVariable + \" points\"");
|
||||
REQUIRE(node != nullptr);
|
||||
|
||||
gd::ExpressionValidator validator(platform, projectScopedContainers, "number|string");
|
||||
node->Visit(validator);
|
||||
REQUIRE(validator.GetFatalErrors().size() == 0);
|
||||
}
|
||||
// A string concatenated with a number variable (will have to be casted to a string in code generation)
|
||||
{
|
||||
auto node = parser.ParseExpression("\"You have \" + MySceneNumberVariable");
|
||||
REQUIRE(node != nullptr);
|
||||
|
||||
gd::ExpressionValidator validator(platform, projectScopedContainers, "number|string");
|
||||
node->Visit(validator);
|
||||
|
||||
REQUIRE(validator.GetFatalErrors().size() == 0);
|
||||
}
|
||||
// A string concatenated with a number variable (will have to be casted to a string in code generation)
|
||||
// and then with a string again.
|
||||
{
|
||||
auto node = parser.ParseExpression("\"You have \" + MySceneNumberVariable + \" points\"");
|
||||
REQUIRE(node != nullptr);
|
||||
|
||||
gd::ExpressionValidator validator(platform, projectScopedContainers, "number|string");
|
||||
node->Visit(validator);
|
||||
|
||||
REQUIRE(validator.GetFatalErrors().size() == 0);
|
||||
}
|
||||
// A string concatenated with an unknown variable (will have to be casted to a string in code generation)
|
||||
// and then with a string again.
|
||||
{
|
||||
auto node = parser.ParseExpression("\"You have \" + MySceneStructureVariable.MyChild.CantKnownTheTypeSoStayGeneric + \" points\"");
|
||||
REQUIRE(node != nullptr);
|
||||
|
||||
gd::ExpressionValidator validator(platform, projectScopedContainers, "number|string");
|
||||
node->Visit(validator);
|
||||
|
||||
REQUIRE(validator.GetFatalErrors().size() == 0);
|
||||
}
|
||||
}
|
||||
SECTION("Expression/parent inferred type is 'number'") {
|
||||
// A trivial test (everything is a string).
|
||||
{
|
||||
auto node = parser.ParseExpression("123 + MySceneNumberVariable + 456");
|
||||
REQUIRE(node != nullptr);
|
||||
|
||||
gd::ExpressionValidator validator(platform, projectScopedContainers, "number|string");
|
||||
node->Visit(validator);
|
||||
REQUIRE(validator.GetFatalErrors().size() == 0);
|
||||
}
|
||||
// A number concatenated with a string variable (will have to be casted to a number in code generation)
|
||||
{
|
||||
auto node = parser.ParseExpression("123 + MySceneStringVariable");
|
||||
REQUIRE(node != nullptr);
|
||||
|
||||
gd::ExpressionValidator validator(platform, projectScopedContainers, "number|string");
|
||||
node->Visit(validator);
|
||||
|
||||
REQUIRE(validator.GetFatalErrors().size() == 0);
|
||||
}
|
||||
// A number concatenated with a string variable (will have to be casted to a number in code generation)
|
||||
// and then with a number again.
|
||||
{
|
||||
auto node = parser.ParseExpression("123 + MySceneStringVariable + 456");
|
||||
REQUIRE(node != nullptr);
|
||||
|
||||
gd::ExpressionValidator validator(platform, projectScopedContainers, "number|string");
|
||||
node->Visit(validator);
|
||||
|
||||
REQUIRE(validator.GetFatalErrors().size() == 0);
|
||||
}
|
||||
// A number concatenated with an unknown variable (will have to be casted to a number in code generation)
|
||||
// and then with a number again.
|
||||
{
|
||||
auto node = parser.ParseExpression("123 + MySceneStructureVariable.MyChild.CantKnownTheTypeSoStayGeneric + 456");
|
||||
REQUIRE(node != nullptr);
|
||||
|
||||
gd::ExpressionValidator validator(platform, projectScopedContainers, "number|string");
|
||||
node->Visit(validator);
|
||||
|
||||
REQUIRE(validator.GetFatalErrors().size() == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Invalid operators with variables having different types than the expression") {
|
||||
// Try to do a sum between numbers in a string expression
|
||||
{
|
||||
auto node = parser.ParseExpression("\"You have \" + MySceneNumberVariable + 2 + \" points\"");
|
||||
REQUIRE(node != nullptr);
|
||||
|
||||
gd::ExpressionValidator validator(platform, projectScopedContainers, "string");
|
||||
node->Visit(validator);
|
||||
|
||||
REQUIRE(validator.GetFatalErrors().size() == 1);
|
||||
REQUIRE(validator.GetFatalErrors()[0]->GetMessage() == "You entered a number, but a text was expected (in quotes).");
|
||||
REQUIRE(validator.GetFatalErrors()[0]->GetStartPosition() == 38);
|
||||
REQUIRE(validator.GetFatalErrors()[0]->GetEndPosition() == 39);
|
||||
}
|
||||
// Try to do a sum between numbers in a number|string expression (that is inferred as a string with the first operand)
|
||||
{
|
||||
auto node = parser.ParseExpression("\"You have \" + MySceneNumberVariable + 2 + \" points\"");
|
||||
REQUIRE(node != nullptr);
|
||||
|
||||
gd::ExpressionValidator validator(platform, projectScopedContainers, "string");
|
||||
node->Visit(validator);
|
||||
|
||||
REQUIRE(validator.GetFatalErrors().size() == 1);
|
||||
REQUIRE(validator.GetFatalErrors()[0]->GetMessage() == "You entered a number, but a text was expected (in quotes).");
|
||||
REQUIRE(validator.GetFatalErrors()[0]->GetStartPosition() == 38);
|
||||
REQUIRE(validator.GetFatalErrors()[0]->GetEndPosition() == 39);
|
||||
}
|
||||
// Try to do a string concatenation in a number expression
|
||||
{
|
||||
auto node = parser.ParseExpression("123 + MySceneStringVariable + \"hello\" + 456");
|
||||
REQUIRE(node != nullptr);
|
||||
|
||||
gd::ExpressionValidator validator(platform, projectScopedContainers, "number");
|
||||
node->Visit(validator);
|
||||
|
||||
REQUIRE(validator.GetFatalErrors().size() == 1);
|
||||
REQUIRE(validator.GetFatalErrors()[0]->GetMessage() == "You entered a text, but a number was expected.");
|
||||
REQUIRE(validator.GetFatalErrors()[0]->GetStartPosition() == 30);
|
||||
REQUIRE(validator.GetFatalErrors()[0]->GetEndPosition() == 37);
|
||||
}
|
||||
// Try to do a string concatenation in a number|string expression (that is inferred as a number with the first operand)
|
||||
{
|
||||
auto node = parser.ParseExpression("123 + MySceneStringVariable + \"hello\" + 456");
|
||||
REQUIRE(node != nullptr);
|
||||
|
||||
gd::ExpressionValidator validator(platform, projectScopedContainers, "number|string");
|
||||
node->Visit(validator);
|
||||
|
||||
REQUIRE(validator.GetFatalErrors().size() == 1);
|
||||
REQUIRE(validator.GetFatalErrors()[0]->GetMessage() == "You entered a text, but a number was expected.");
|
||||
REQUIRE(validator.GetFatalErrors()[0]->GetStartPosition() == 30);
|
||||
REQUIRE(validator.GetFatalErrors()[0]->GetEndPosition() == 37);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Valid function call with object variable") {
|
||||
{
|
||||
// Note that in this test we need to use an expression with "objectvar",
|
||||
|
@@ -71,7 +71,7 @@ TEST_CASE("ObjectAssetSerializer", "[common]") {
|
||||
frame.SetImageName("assets/Idle.png");
|
||||
direction.AddSprite(frame);
|
||||
|
||||
spriteConfiguration->AddAnimation(animation);
|
||||
spriteConfiguration->GetAnimations().AddAnimation(animation);
|
||||
}
|
||||
|
||||
SerializerElement assetElement;
|
||||
|
@@ -35,7 +35,7 @@ void SetupSpriteConfiguration(gd::ObjectConfiguration &configuration) {
|
||||
REQUIRE(spriteConfiguration != nullptr);
|
||||
gd::Animation animation;
|
||||
animation.SetName("Idle");
|
||||
spriteConfiguration->AddAnimation(animation);
|
||||
spriteConfiguration->GetAnimations().AddAnimation(animation);
|
||||
};
|
||||
|
||||
gd::Object &SetupProjectWithSprite(gd::Project &project,
|
||||
@@ -83,9 +83,9 @@ void CheckSpriteConfigurationInProjectElement(
|
||||
void CheckSpriteConfiguration(gd::ObjectConfiguration &configuration) {
|
||||
auto *spriteConfiguration = dynamic_cast<gd::SpriteObject *>(&configuration);
|
||||
REQUIRE(spriteConfiguration);
|
||||
REQUIRE(spriteConfiguration->GetAnimationsCount() == 1);
|
||||
REQUIRE(spriteConfiguration->GetAnimations().GetAnimationsCount() == 1);
|
||||
|
||||
auto &animation = spriteConfiguration->GetAnimation(0);
|
||||
auto &animation = spriteConfiguration->GetAnimations().GetAnimation(0);
|
||||
REQUIRE(animation.GetName() == "Idle");
|
||||
};
|
||||
|
||||
|
@@ -105,7 +105,7 @@ namespace gdjs {
|
||||
if (this._isUntransformedHitBoxesDirty) {
|
||||
this._updateUntransformedHitBoxes();
|
||||
}
|
||||
return this._minZ;
|
||||
return this._z + this._minZ;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -1,4 +1,7 @@
|
||||
namespace gdjs {
|
||||
export interface PixiImageManager {
|
||||
_threeAnimationFrameTextureManager: ThreeAnimationFrameTextureManager;
|
||||
}
|
||||
/**
|
||||
* The renderer for a {@link gdjs.CustomRuntimeObject3D} using Three.js.
|
||||
*/
|
||||
@@ -80,7 +83,7 @@ namespace gdjs {
|
||||
|
||||
threeObject3D.visible = !this._object.hidden;
|
||||
|
||||
this._isContainerDirty = true;
|
||||
this._isContainerDirty = false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -131,5 +134,46 @@ namespace gdjs {
|
||||
setLayerIndex(layer: gdjs.RuntimeLayer, index: float): void {
|
||||
// Layers are not handled for 3D custom objects.
|
||||
}
|
||||
|
||||
static getAnimationFrameTextureManager(
|
||||
imageManager: gdjs.PixiImageManager
|
||||
): ThreeAnimationFrameTextureManager {
|
||||
if (!imageManager._threeAnimationFrameTextureManager) {
|
||||
imageManager._threeAnimationFrameTextureManager = new ThreeAnimationFrameTextureManager(
|
||||
imageManager
|
||||
);
|
||||
}
|
||||
return imageManager._threeAnimationFrameTextureManager;
|
||||
}
|
||||
}
|
||||
|
||||
class ThreeAnimationFrameTextureManager
|
||||
implements gdjs.AnimationFrameTextureManager<THREE.Material> {
|
||||
private _imageManager: gdjs.PixiImageManager;
|
||||
|
||||
constructor(imageManager: gdjs.PixiImageManager) {
|
||||
this._imageManager = imageManager;
|
||||
}
|
||||
|
||||
getAnimationFrameTexture(imageName: string) {
|
||||
return this._imageManager.getThreeMaterial(imageName, {
|
||||
useTransparentTexture: true,
|
||||
forceBasicMaterial: true,
|
||||
});
|
||||
}
|
||||
|
||||
getAnimationFrameWidth(material: THREE.Material) {
|
||||
const map = (material as
|
||||
| THREE.MeshBasicMaterial
|
||||
| THREE.MeshStandardMaterial).map;
|
||||
return map ? map.image.width : 0;
|
||||
}
|
||||
|
||||
getAnimationFrameHeight(material: THREE.Material) {
|
||||
const map = (material as
|
||||
| THREE.MeshBasicMaterial
|
||||
| THREE.MeshStandardMaterial).map;
|
||||
return map ? map.image.height : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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.
|
||||
@@ -3179,14 +3134,51 @@ module.exports = {
|
||||
modelDepth < epsilon
|
||||
? Number.POSITIVE_INFINITY
|
||||
: originalDepth / modelDepth;
|
||||
let scaleRatio = Math.min(widthRatio, heightRatio, depthRatio);
|
||||
if (!Number.isFinite(scaleRatio)) {
|
||||
scaleRatio = 1;
|
||||
}
|
||||
const minScaleRatio = Math.min(widthRatio, heightRatio, depthRatio);
|
||||
if (!Number.isFinite(minScaleRatio)) {
|
||||
this._defaultWidth = modelWidth;
|
||||
this._defaultHeight = modelHeight;
|
||||
this._defaultDepth = modelDepth;
|
||||
} else {
|
||||
if (widthRatio === minScaleRatio) {
|
||||
this._defaultWidth = originalWidth;
|
||||
this._defaultHeight = Rendered3DInstance.applyRatio({
|
||||
oldReferenceValue: modelWidth,
|
||||
newReferenceValue: originalWidth,
|
||||
valueToApplyTo: modelHeight,
|
||||
});
|
||||
this._defaultDepth = Rendered3DInstance.applyRatio({
|
||||
oldReferenceValue: modelWidth,
|
||||
newReferenceValue: originalWidth,
|
||||
valueToApplyTo: modelDepth,
|
||||
});
|
||||
} else if (heightRatio === minScaleRatio) {
|
||||
this._defaultWidth = Rendered3DInstance.applyRatio({
|
||||
oldReferenceValue: modelHeight,
|
||||
newReferenceValue: originalHeight,
|
||||
valueToApplyTo: modelWidth,
|
||||
});
|
||||
|
||||
this._defaultWidth = scaleRatio * modelWidth;
|
||||
this._defaultHeight = scaleRatio * modelHeight;
|
||||
this._defaultDepth = scaleRatio * modelDepth;
|
||||
this._defaultHeight = originalHeight;
|
||||
this._defaultDepth = Rendered3DInstance.applyRatio({
|
||||
oldReferenceValue: modelHeight,
|
||||
newReferenceValue: originalHeight,
|
||||
valueToApplyTo: modelDepth,
|
||||
});
|
||||
} else {
|
||||
this._defaultWidth = Rendered3DInstance.applyRatio({
|
||||
oldReferenceValue: modelDepth,
|
||||
newReferenceValue: originalDepth,
|
||||
valueToApplyTo: modelWidth,
|
||||
});
|
||||
this._defaultHeight = Rendered3DInstance.applyRatio({
|
||||
oldReferenceValue: modelDepth,
|
||||
newReferenceValue: originalDepth,
|
||||
valueToApplyTo: modelHeight,
|
||||
});
|
||||
this._defaultDepth = originalDepth;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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(
|
||||
@@ -41,6 +33,14 @@ module.exports = {
|
||||
.addInstructionOrExpressionGroupMetadata(_('AdMob'))
|
||||
.setIcon('JsPlatform/Extensions/admobicon24.png');
|
||||
|
||||
extension
|
||||
.addDependency()
|
||||
.setName('Consent Cordova plugin')
|
||||
.setDependencyType('cordova')
|
||||
.setExportName('cordova-plugin-consent')
|
||||
.setVersion('2.4.0')
|
||||
.onlyIfOtherDependencyIsExported('AdMob Cordova plugin');
|
||||
|
||||
extension
|
||||
.registerProperty('AdMobAppIdAndroid')
|
||||
.setLabel(_('AdMob Android App ID'))
|
||||
@@ -71,13 +71,6 @@ module.exports = {
|
||||
)
|
||||
.onlyIfSomeExtraSettingsNonEmpty();
|
||||
|
||||
extension
|
||||
.addDependency()
|
||||
.setName('Consent Cordova plugin')
|
||||
.setDependencyType('cordova')
|
||||
.setExportName('cordova-plugin-consent')
|
||||
.onlyIfOtherDependencyIsExported('AdMob Cordova plugin');
|
||||
|
||||
extension
|
||||
.addAction(
|
||||
'SetTestMode',
|
||||
@@ -789,10 +782,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 [];
|
||||
},
|
||||
};
|
||||
|
238
Extensions/JsExtensionTypes.d.ts
vendored
Normal file
238
Extensions/JsExtensionTypes.d.ts
vendored
Normal file
@@ -0,0 +1,238 @@
|
||||
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;
|
||||
|
||||
/**
|
||||
* Applies ratio to value without intermediary value to avoid precision issues.
|
||||
*/
|
||||
static applyRatio({
|
||||
oldReferenceValue,
|
||||
newReferenceValue,
|
||||
valueToApplyTo,
|
||||
}: {
|
||||
oldReferenceValue: number;
|
||||
newReferenceValue: number;
|
||||
valueToApplyTo: 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';
|
||||
}
|
||||
|
||||
|
10
Extensions/P2P/A_peer.js
vendored
10
Extensions/P2P/A_peer.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -422,6 +422,17 @@ namespace gdjs {
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Forces the usage of a relay (TURN) server, to avoid sharing IP addresses with the other peers.
|
||||
* @param shouldUseRelayServer Whether relay-only should be enabled or disabled.
|
||||
*/
|
||||
export const forceUseRelayServer = (shouldUseRelayServer: boolean) => {
|
||||
peerConfig.config = peerConfig.config || {};
|
||||
peerConfig.config.iceTransportPolicy = shouldUseRelayServer
|
||||
? 'relay'
|
||||
: 'all';
|
||||
};
|
||||
|
||||
/**
|
||||
* Overrides the default peer ID. Must be called before connecting to a broker.
|
||||
* Overriding the ID may have unwanted consequences. Do not use this feature
|
||||
|
@@ -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(
|
||||
@@ -182,6 +174,33 @@ module.exports = {
|
||||
.addIncludeFile('Extensions/P2P/B_p2ptools.js')
|
||||
.setFunctionName('gdjs.evtTools.p2p.useCustomICECandidate');
|
||||
|
||||
extension
|
||||
.addAction(
|
||||
'ForceRelayServer',
|
||||
_('Disable IP address sharing'),
|
||||
_(
|
||||
'Disables the sharing of IP addresses with the other peers. ' +
|
||||
'This action needs to be called BEFORE connecting to the broker server.'
|
||||
),
|
||||
_('Disable IP sharing: _PARAM0_'),
|
||||
'',
|
||||
'JsPlatform/Extensions/p2picon.svg',
|
||||
'JsPlatform/Extensions/p2picon.svg'
|
||||
)
|
||||
.addParameter(
|
||||
'yesorno',
|
||||
_('Disable sharing of IP addresses'),
|
||||
'Generally, it is recommended to keep sharing of IP addressed enabled ' +
|
||||
'to make connections faster and more often possible. ' +
|
||||
'Disabling IP address sharing will force all connections to pass messages through a ' +
|
||||
'TURN relay server, you can make P2P use one by adding one as an ICE candidate.',
|
||||
false
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile('Extensions/P2P/A_peer.js')
|
||||
.addIncludeFile('Extensions/P2P/B_p2ptools.js')
|
||||
.setFunctionName('gdjs.evtTools.p2p.forceUseRelayServer');
|
||||
|
||||
extension
|
||||
.addAction(
|
||||
'UseDefaultBroker',
|
||||
@@ -474,10 +493,7 @@ module.exports = {
|
||||
|
||||
return extension;
|
||||
},
|
||||
runExtensionSanityTests: function (
|
||||
gd /*: libGDevelop */,
|
||||
extension /*: gdPlatformExtension*/
|
||||
) {
|
||||
runExtensionSanityTests: function (gd, extension) {
|
||||
return [];
|
||||
},
|
||||
};
|
||||
|
@@ -68,7 +68,10 @@ namespace gdjs {
|
||||
max: objectData.particleLifeTimeMax,
|
||||
},
|
||||
// A negative flow is "infinite flow" (all particles burst)
|
||||
frequency: objectData.flow < 0 ? 0.0001 : 1.0 / objectData.flow,
|
||||
frequency:
|
||||
objectData.flow < 0
|
||||
? ParticleEmitterObjectPixiRenderer.frequencyMinimumValue
|
||||
: 1.0 / objectData.flow,
|
||||
spawnChance: 1,
|
||||
particlesPerWave: objectData.flow < 0 ? objectData.maxParticleNb : 1,
|
||||
maxParticles: objectData.maxParticleNb,
|
||||
@@ -347,7 +350,10 @@ namespace gdjs {
|
||||
}
|
||||
|
||||
setFlow(flow: number, tank: number): void {
|
||||
this.emitter.frequency = flow < 0 ? 0.0001 : 1.0 / flow;
|
||||
this.emitter.frequency =
|
||||
flow < 0
|
||||
? ParticleEmitterObjectPixiRenderer.frequencyMinimumValue
|
||||
: 1.0 / flow;
|
||||
this.emitter.emitterLifetime = ParticleEmitterObjectPixiRenderer.computeLifetime(
|
||||
flow,
|
||||
tank
|
||||
@@ -420,11 +426,33 @@ namespace gdjs {
|
||||
return this.started;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns `true` at the end of emission or at the start if it's paused.
|
||||
* Returns false if there is no limit.
|
||||
*/
|
||||
_mayHaveEndedEmission(): boolean {
|
||||
return (
|
||||
// No end can be reached if there is no flow.
|
||||
this.emitter.frequency >
|
||||
ParticleEmitterObjectPixiRenderer.frequencyMinimumValue &&
|
||||
// No end can be reached when there is no limit.
|
||||
this.emitter.emitterLifetime >= 0 &&
|
||||
// Pixi stops the emission at the end.
|
||||
!this.emitter.emit &&
|
||||
// Pixi reset `_emitterLife` to `emitterLifetime` at the end of emission
|
||||
// so there is no way to know if it is the end or the start.
|
||||
// @ts-ignore Use a private attribute.
|
||||
this.emitter._emitterLife === this.emitter.emitterLifetime
|
||||
);
|
||||
}
|
||||
|
||||
static computeLifetime(flow: number, tank: number): float {
|
||||
if (tank < 0) return -1;
|
||||
else if (flow < 0) return 0.001;
|
||||
else return (tank + 0.1) / flow;
|
||||
}
|
||||
|
||||
private static readonly frequencyMinimumValue = 0.0001;
|
||||
}
|
||||
|
||||
// @ts-ignore - Register the class to let the engine use it.
|
||||
|
@@ -113,6 +113,11 @@ namespace gdjs {
|
||||
_additiveRenderingDirty: boolean = true;
|
||||
// Don't mark texture as dirty if not using one.
|
||||
_textureDirty: boolean;
|
||||
/**
|
||||
* `true` only when the emission is paused by events.
|
||||
* It allows to tell the end of emission apart from it.
|
||||
*/
|
||||
_isEmissionPaused: boolean = false;
|
||||
|
||||
// @ts-ignore
|
||||
_renderer: gdjs.ParticleEmitterObjectRenderer;
|
||||
@@ -390,9 +395,11 @@ namespace gdjs {
|
||||
this._additiveRenderingDirty = this._maxParticlesCountDirty = this._particleRotationSpeedDirty = false;
|
||||
this._renderer.update(this.getElapsedTime() / 1000.0);
|
||||
if (
|
||||
this._renderer.hasStarted() &&
|
||||
this.destroyWhenNoParticles &&
|
||||
this.getParticleCount() === 0 &&
|
||||
this.destroyWhenNoParticles
|
||||
this._renderer.hasStarted() &&
|
||||
!this._isEmissionPaused &&
|
||||
this._renderer._mayHaveEndedEmission()
|
||||
) {
|
||||
this.deleteFromScene(instanceContainer);
|
||||
}
|
||||
@@ -803,10 +810,12 @@ namespace gdjs {
|
||||
}
|
||||
|
||||
startEmission(): void {
|
||||
this._isEmissionPaused = false;
|
||||
this._renderer.start();
|
||||
}
|
||||
|
||||
stopEmission(): void {
|
||||
this._isEmissionPaused = true;
|
||||
this._renderer.stop();
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
)
|
||||
@@ -561,7 +586,8 @@ module.exports = {
|
||||
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
|
||||
.addParameter('expression', _('Time scale (1 by default)'))
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile('Extensions/Physics2Behavior/physics2tools.js')
|
||||
.addIncludeFile('Extensions/Physics2Behavior/physics2tools.js')
|
||||
.addIncludeFile('Extensions/Physics2Behavior/physics2runtimebehavior.js')
|
||||
.setFunctionName('gdjs.physics2.setTimeScale');
|
||||
|
||||
aut
|
||||
@@ -775,10 +801,10 @@ module.exports = {
|
||||
.setDefaultValue('true')
|
||||
.getCodeExtraInformation()
|
||||
.setFunctionName('setSleepingAllowed');
|
||||
|
||||
|
||||
// Deprecated action (fixed typo):
|
||||
aut
|
||||
.addDuplicatedAction("SetSleepingaAllowed", "SetSleepingAllowed")
|
||||
.addDuplicatedAction('SetSleepingaAllowed', 'SetSleepingAllowed')
|
||||
.setHidden();
|
||||
|
||||
aut
|
||||
@@ -1390,6 +1416,26 @@ module.exports = {
|
||||
.getCodeExtraInformation()
|
||||
.setFunctionName('getLinearVelocityAngle');
|
||||
|
||||
aut
|
||||
.addAction(
|
||||
'LinearVelocityAngle',
|
||||
_('Linear velocity towards an angle'),
|
||||
_('Set the linear velocity towards an angle.'),
|
||||
_(
|
||||
'Set the linear velocity of _PARAM0_ towards angle: _PARAM2_ degrees, speed: _PARAM3_ pixels per second'
|
||||
),
|
||||
_('Velocity'),
|
||||
'res/physics32.png',
|
||||
'res/physics32.png'
|
||||
)
|
||||
.addParameter('object', _('Object'), '', false)
|
||||
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
|
||||
.addParameter('expression', _('Angle'))
|
||||
.addParameter('expression', _('Speed (in pixels per second)'))
|
||||
.getCodeExtraInformation()
|
||||
.setFunctionName('setLinearVelocityAngle')
|
||||
.setGetter('getLinearVelocityAngle');
|
||||
|
||||
aut
|
||||
.addExpression(
|
||||
'LinearVelocityAngle',
|
||||
@@ -1476,10 +1522,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 +1551,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 +1581,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 +1610,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 +1642,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 +1672,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 +1703,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 +1724,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');
|
||||
|
||||
@@ -4019,7 +4095,8 @@ module.exports = {
|
||||
.addParameter('objectList', _('Object'), '', false)
|
||||
.addCodeOnlyParameter('conditionInverted', '')
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile('Extensions/Physics2Behavior/physics2tools.js')
|
||||
.addIncludeFile('Extensions/Physics2Behavior/physics2tools.js')
|
||||
.addIncludeFile('Extensions/Physics2Behavior/physics2runtimebehavior.js')
|
||||
.setFunctionName('gdjs.physics2.objectsCollide');
|
||||
|
||||
extension
|
||||
@@ -4037,7 +4114,8 @@ module.exports = {
|
||||
.addParameter('objectList', _('Object'), '', false)
|
||||
.addCodeOnlyParameter('conditionInverted', '')
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile('Extensions/Physics2Behavior/physics2tools.js')
|
||||
.addIncludeFile('Extensions/Physics2Behavior/physics2tools.js')
|
||||
.addIncludeFile('Extensions/Physics2Behavior/physics2runtimebehavior.js')
|
||||
.setFunctionName('gdjs.physics2.haveObjectsStartedColliding');
|
||||
|
||||
extension
|
||||
@@ -4055,16 +4133,14 @@ module.exports = {
|
||||
.addParameter('objectList', _('Object'), '', false)
|
||||
.addCodeOnlyParameter('conditionInverted', '')
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile('Extensions/Physics2Behavior/physics2tools.js')
|
||||
.addIncludeFile('Extensions/Physics2Behavior/physics2tools.js')
|
||||
.addIncludeFile('Extensions/Physics2Behavior/physics2runtimebehavior.js')
|
||||
.setFunctionName('gdjs.physics2.haveObjectsStoppedColliding');
|
||||
|
||||
return extension;
|
||||
},
|
||||
|
||||
runExtensionSanityTests: function (
|
||||
gd /*: libGDevelop */,
|
||||
extension /*: gdPlatformExtension*/
|
||||
) {
|
||||
runExtensionSanityTests: function (gd, extension) {
|
||||
const dummyBehavior = extension
|
||||
.getBehaviorMetadata('Physics2::Physics2Behavior')
|
||||
.get();
|
||||
|
@@ -1429,6 +1429,23 @@ namespace gdjs {
|
||||
);
|
||||
}
|
||||
|
||||
setLinearVelocityAngle(angle: float, linearVelocity: float): void {
|
||||
// If there is no body, set a new one
|
||||
if (this._body === null) {
|
||||
if (!this.createBody()) return;
|
||||
}
|
||||
const body = this._body!;
|
||||
|
||||
// Set the linear velocity toward an angle
|
||||
angle = gdjs.toRad(angle);
|
||||
body.SetLinearVelocity(
|
||||
this.b2Vec2(
|
||||
linearVelocity * Math.cos(angle) * this._sharedData.invScaleX,
|
||||
linearVelocity * Math.sin(angle) * this._sharedData.invScaleY
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
getAngularVelocity(): float {
|
||||
// If there is no body, set a new one
|
||||
if (this._body === null) {
|
||||
|
@@ -872,6 +872,5 @@ void DeclarePlatformBehaviorExtension(gd::PlatformExtension& extension) {
|
||||
.AddParameter("objectList", _("Object"), "", false)
|
||||
.AddParameter("behavior", _("Behavior"), "PlatformerObjectBehavior")
|
||||
.AddParameter("objectList", _("Platforms"), "", false)
|
||||
.AddCodeOnlyParameter("conditionInverted", "")
|
||||
.SetFunctionName("gdjs.evtTools.platform.isOnPlatform");
|
||||
.AddCodeOnlyParameter("conditionInverted", "");
|
||||
}
|
||||
|
@@ -41,6 +41,17 @@ class PlatformBehaviorJsExtension : public gd::PlatformExtension {
|
||||
.AddIncludeFile(
|
||||
"Extensions/PlatformBehavior/platformtools.js");
|
||||
|
||||
std::map<gd::String, gd::InstructionMetadata>& extConditions =
|
||||
GetAllConditions();
|
||||
extConditions["PlatformBehavior::IsObjectOnGivenFloor"].SetFunctionName(
|
||||
"gdjs.evtTools.platform.isOnPlatform")
|
||||
.AddIncludeFile(
|
||||
"Extensions/PlatformBehavior/platformruntimebehavior.js")
|
||||
.AddIncludeFile(
|
||||
"Extensions/PlatformBehavior/platformerobjectruntimebehavior.js")
|
||||
.AddIncludeFile(
|
||||
"Extensions/PlatformBehavior/platformtools.js");
|
||||
|
||||
{
|
||||
std::map<gd::String, gd::InstructionMetadata>& autActions =
|
||||
GetAllActionsForBehavior(
|
||||
|
@@ -262,6 +262,9 @@ namespace gdjs {
|
||||
const behavior1 = object1.getBehavior(
|
||||
behaviorName
|
||||
) as PlatformerObjectRuntimeBehavior;
|
||||
if (!behavior1) {
|
||||
return false;
|
||||
}
|
||||
return behavior1.isOnFloorObject(object2);
|
||||
}
|
||||
}
|
||||
|
@@ -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 {
|
||||
@@ -163,6 +148,9 @@ module.exports = {
|
||||
this._instance.getX(),
|
||||
this._instance.getY()
|
||||
);
|
||||
this._pixiObject.rotation = RenderedInstance.toRad(
|
||||
this._instance.getAngle()
|
||||
);
|
||||
|
||||
this.setAnimation(this._instance.getRawDoubleProperty('animation'));
|
||||
|
||||
@@ -203,6 +191,14 @@ module.exports = {
|
||||
return -this._spineOriginOffsetY;
|
||||
}
|
||||
|
||||
getCenterX() {
|
||||
return this.getOriginX();
|
||||
}
|
||||
|
||||
getCenterY() {
|
||||
return this.getOriginY();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} index - animation index
|
||||
*/
|
||||
@@ -228,7 +224,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
|
||||
|
@@ -124,6 +124,16 @@ namespace gdjs {
|
||||
return this.getY() + originOffset.y;
|
||||
}
|
||||
|
||||
getCenterX(): float {
|
||||
const originOffset = this._renderer.getOriginOffset();
|
||||
return -originOffset.x;
|
||||
}
|
||||
|
||||
getCenterY(): float {
|
||||
const originOffset = this._renderer.getOriginOffset();
|
||||
return -originOffset.y;
|
||||
}
|
||||
|
||||
onDestroyed(): void {
|
||||
super.onDestroyed();
|
||||
this._renderer.onDestroy();
|
||||
|
@@ -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,17 @@ gd::ObjectMetadata &MetadataDeclarationHelper::DeclareObjectMetadata(
|
||||
.AddDefaultBehavior("Scene3D::Base3DBehavior");
|
||||
}
|
||||
else {
|
||||
objectMetadata.AddDefaultBehavior("EffectCapability::EffectBehavior");
|
||||
objectMetadata.AddDefaultBehavior("OpacityCapability::OpacityBehavior");
|
||||
}
|
||||
if (eventsBasedObject.IsAnimatable()) {
|
||||
objectMetadata
|
||||
.AddDefaultBehavior("AnimatableCapability::AnimatableBehavior");
|
||||
}
|
||||
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 +1521,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 +1556,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
|
||||
|
@@ -78,7 +78,7 @@ gd::String ObjectCodeGenerator::GenerateRuntimeObjectCompleteCode(
|
||||
methodFullyQualifiedName,
|
||||
"that._onceTriggers",
|
||||
functionName == doStepPreEventsFunctionName
|
||||
? GenerateDoStepPreEventsPreludeCode()
|
||||
? GenerateDoStepPreEventsPreludeCode(eventsBasedObject)
|
||||
: "",
|
||||
functionName == onCreatedFunctionName
|
||||
? "gdjs.CustomRuntimeObject.prototype.onCreated.call(this);\n"
|
||||
@@ -109,6 +109,77 @@ gd::String ObjectCodeGenerator::GenerateRuntimeObjectCompleteCode(
|
||||
}
|
||||
|
||||
return updateFromObjectCode;
|
||||
},
|
||||
// generateInitializeAnimatableCode
|
||||
[&]() {
|
||||
return gd::String(R"jscode_template(
|
||||
this._animator = new gdjs.SpriteAnimator(
|
||||
objectData.animatable.animations,
|
||||
gdjs.RENDERER_CLASS_NAME.getAnimationFrameTextureManager(
|
||||
parentInstanceContainer.getGame().getImageManager()));
|
||||
)jscode_template")
|
||||
.FindAndReplace("RENDERER_CLASS_NAME", eventsBasedObject.IsRenderedIn3D() ? "CustomRuntimeObject3DRenderer" : "CustomRuntimeObject2DRenderer");
|
||||
},
|
||||
// generateAnimatableCode
|
||||
[&]() {
|
||||
return gd::String(R"jscode_template(
|
||||
// gdjs.Animatable interface implementation
|
||||
getAnimator() {
|
||||
return this._animator;
|
||||
}
|
||||
getAnimationIndex() {
|
||||
return this._animator.getAnimationIndex();
|
||||
}
|
||||
setAnimationIndex(animationIndex) {
|
||||
this._animator.setAnimationIndex(animationIndex);
|
||||
}
|
||||
getAnimationName() {
|
||||
return this._animator.getAnimationName();
|
||||
}
|
||||
setAnimationName(animationName) {
|
||||
this._animator.setAnimationName(animationName);
|
||||
}
|
||||
hasAnimationEnded() {
|
||||
return this._animator.hasAnimationEnded();
|
||||
}
|
||||
isAnimationPaused() {
|
||||
return this._animator.isAnimationPaused();
|
||||
}
|
||||
pauseAnimation() {
|
||||
this._animator.pauseAnimation();
|
||||
}
|
||||
resumeAnimation() {
|
||||
this._animator.resumeAnimation();
|
||||
}
|
||||
getAnimationSpeedScale() {
|
||||
return this._animator.getAnimationSpeedScale();
|
||||
}
|
||||
setAnimationSpeedScale(ratio) {
|
||||
this._animator.setAnimationSpeedScale(ratio);
|
||||
}
|
||||
getAnimationElapsedTime() {
|
||||
return this._animator.getAnimationElapsedTime();
|
||||
}
|
||||
setAnimationElapsedTime(time) {
|
||||
this._animator.setAnimationElapsedTime(time);
|
||||
}
|
||||
getAnimationDuration() {
|
||||
return this._animator.getAnimationDuration();
|
||||
}
|
||||
)jscode_template");
|
||||
},
|
||||
// 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 +190,10 @@ 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()> generateInitializeAnimatableCode,
|
||||
std::function<gd::String()> generateAnimatableCode,
|
||||
std::function<gd::String()> generateTextContainerCode) {
|
||||
return gd::String(R"jscode_template(
|
||||
CODE_NAMESPACE = CODE_NAMESPACE || {};
|
||||
|
||||
@@ -134,6 +208,7 @@ CODE_NAMESPACE.RUNTIME_OBJECT_CLASSNAME = class RUNTIME_OBJECT_CLASSNAME extends
|
||||
this._onceTriggers = new gdjs.OnceTriggers();
|
||||
this._objectData = {};
|
||||
INITIALIZE_PROPERTIES_CODE
|
||||
INITIALIZE_ANIMATABLE_CODE
|
||||
|
||||
// It calls the onCreated super implementation at the end.
|
||||
this.onCreated();
|
||||
@@ -149,6 +224,10 @@ CODE_NAMESPACE.RUNTIME_OBJECT_CLASSNAME = class RUNTIME_OBJECT_CLASSNAME extends
|
||||
|
||||
// Properties:
|
||||
PROPERTIES_CODE
|
||||
|
||||
ANIMATABLE_CODE
|
||||
|
||||
TEXT_CONTAINER_CODE
|
||||
}
|
||||
|
||||
// Methods:
|
||||
@@ -166,8 +245,14 @@ gdjs.registerObject("EXTENSION_NAME::OBJECT_NAME", CODE_NAMESPACE.RUNTIME_OBJECT
|
||||
.FindAndReplace("CODE_NAMESPACE", codeNamespace)
|
||||
.FindAndReplace("INITIALIZE_PROPERTIES_CODE",
|
||||
generateInitializePropertiesCode())
|
||||
.FindAndReplace("INITIALIZE_ANIMATABLE_CODE",
|
||||
eventsBasedObject.IsAnimatable()
|
||||
? generateInitializeAnimatableCode()
|
||||
: "")
|
||||
.FindAndReplace("UPDATE_FROM_OBJECT_DATA_CODE", generateUpdateFromObjectDataCode())
|
||||
.FindAndReplace("PROPERTIES_CODE", generatePropertiesCode())
|
||||
.FindAndReplace("ANIMATABLE_CODE", eventsBasedObject.IsAnimatable() ? generateAnimatableCode() : "")
|
||||
.FindAndReplace("TEXT_CONTAINER_CODE", eventsBasedObject.IsTextContainer() ? generateTextContainerCode() : "")
|
||||
.FindAndReplace("METHODS_CODE", generateMethodsCode());
|
||||
;
|
||||
}
|
||||
@@ -265,11 +350,18 @@ CODE_NAMESPACE.RUNTIME_OBJECT_CLASSNAME.prototype.doStepPreEvents = function() {
|
||||
.FindAndReplace("RUNTIME_OBJECT_CLASSNAME",
|
||||
eventsBasedObject.GetName())
|
||||
.FindAndReplace("CODE_NAMESPACE", codeNamespace)
|
||||
.FindAndReplace("PRELUDE_CODE", GenerateDoStepPreEventsPreludeCode());
|
||||
}
|
||||
.FindAndReplace("PRELUDE_CODE",
|
||||
GenerateDoStepPreEventsPreludeCode(eventsBasedObject));}
|
||||
|
||||
gd::String ObjectCodeGenerator::GenerateDoStepPreEventsPreludeCode() {
|
||||
return "this._onceTriggers.startNewFrame();";
|
||||
gd::String ObjectCodeGenerator::GenerateDoStepPreEventsPreludeCode(
|
||||
const gd::EventsBasedObject& eventsBasedObject) {
|
||||
gd::String doStepPreEventsPreludeCode;
|
||||
doStepPreEventsPreludeCode += "this._onceTriggers.startNewFrame();";
|
||||
if (eventsBasedObject.IsAnimatable()) {
|
||||
doStepPreEventsPreludeCode +=
|
||||
"\nthis._animator.step(this.getElapsedTime() / 1000);";
|
||||
}
|
||||
return doStepPreEventsPreludeCode;
|
||||
}
|
||||
|
||||
} // namespace gdjs
|
||||
|
@@ -74,7 +74,10 @@ 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()> generateInitializeAnimatableCode,
|
||||
std::function<gd::String()> generateAnimatableCode,
|
||||
std::function<gd::String()> generateTextContainerCode);
|
||||
|
||||
gd::String GenerateRuntimeObjectPropertyTemplateCode(
|
||||
const gd::EventsBasedObject& eventsBasedObject,
|
||||
@@ -104,7 +107,8 @@ class ObjectCodeGenerator {
|
||||
const gd::EventsBasedObject& eventsBasedObject,
|
||||
const gd::String& codeNamespace);
|
||||
|
||||
gd::String GenerateDoStepPreEventsPreludeCode();
|
||||
gd::String GenerateDoStepPreEventsPreludeCode(
|
||||
const gd::EventsBasedObject& eventsBasedObject);
|
||||
|
||||
gd::Project& project;
|
||||
|
||||
|
@@ -745,6 +745,7 @@ void ExporterHelper::AddLibsInclude(bool pixiRenderers,
|
||||
InsertUnique(includesFiles, "variablescontainer.js");
|
||||
InsertUnique(includesFiles, "oncetriggers.js");
|
||||
InsertUnique(includesFiles, "runtimebehavior.js");
|
||||
InsertUnique(includesFiles, "SpriteAnimator.js");
|
||||
InsertUnique(includesFiles, "spriteruntimeobject.js");
|
||||
InsertUnique(includesFiles, "affinetransformation.js");
|
||||
InsertUnique(includesFiles, "CustomRuntimeObjectInstanceContainer.js");
|
||||
|
@@ -9,6 +9,7 @@ namespace gdjs {
|
||||
};
|
||||
|
||||
export type CustomObjectConfiguration = ObjectConfiguration & {
|
||||
animatable?: SpriteAnimationData[];
|
||||
childrenContent: { [objectName: string]: ObjectConfiguration & any };
|
||||
};
|
||||
|
||||
@@ -86,10 +87,30 @@ namespace gdjs {
|
||||
oldObjectData: ObjectData & CustomObjectConfiguration,
|
||||
newObjectData: ObjectData & CustomObjectConfiguration
|
||||
): boolean {
|
||||
const animator = this.getAnimator();
|
||||
if (animator) {
|
||||
animator.updateFromObjectData(
|
||||
oldObjectData.animatable || [],
|
||||
newObjectData.animatable || []
|
||||
);
|
||||
}
|
||||
return this._instanceContainer.updateFrom(oldObjectData, newObjectData);
|
||||
}
|
||||
|
||||
extraInitializationFromInitialInstance(initialInstanceData: InstanceData) {
|
||||
const animator = this.getAnimator();
|
||||
if (initialInstanceData.numberProperties) {
|
||||
for (
|
||||
let i = 0, len = initialInstanceData.numberProperties.length;
|
||||
i < len;
|
||||
++i
|
||||
) {
|
||||
const extraData = initialInstanceData.numberProperties[i];
|
||||
if (animator && extraData.name === 'animation') {
|
||||
animator.setAnimationIndex(extraData.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (initialInstanceData.customSize) {
|
||||
this.setWidth(initialInstanceData.width);
|
||||
this.setHeight(initialInstanceData.height);
|
||||
@@ -658,6 +679,15 @@ namespace gdjs {
|
||||
isFlippedY(): boolean {
|
||||
return this._flippedY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the sprite animator.
|
||||
*
|
||||
* It returns `null` when custom objects don't have the Animatable capability.
|
||||
*/
|
||||
getAnimator(): gdjs.SpriteAnimator<any> | null {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Others initialization and internal state management :
|
||||
|
717
GDJS/Runtime/SpriteAnimator.ts
Normal file
717
GDJS/Runtime/SpriteAnimator.ts
Normal file
@@ -0,0 +1,717 @@
|
||||
namespace gdjs {
|
||||
/** Represents a point in a coordinate system. */
|
||||
export type SpritePoint = {
|
||||
/** X position of the point. */
|
||||
x: float;
|
||||
/** Y position of the point. */
|
||||
y: float;
|
||||
};
|
||||
|
||||
/** Represents a custom point in a frame. */
|
||||
export type SpriteCustomPointData = {
|
||||
/** Name of the point. */
|
||||
name: string;
|
||||
/** X position of the point. */
|
||||
x: float;
|
||||
/** Y position of the point. */
|
||||
y: float;
|
||||
};
|
||||
|
||||
/** Represents the center point in a frame. */
|
||||
export type SpriteCenterPointData = {
|
||||
/** Name of the point. */
|
||||
name: string;
|
||||
/** Is the center automatically computed? */
|
||||
automatic: boolean;
|
||||
/** X position of the point. */
|
||||
x: float;
|
||||
/** Y position of the point. */
|
||||
y: float;
|
||||
};
|
||||
|
||||
/** Represents a {@link gdjs.SpriteAnimationFrame}. */
|
||||
export type SpriteFrameData = {
|
||||
/** The resource name of the image used in this frame. */
|
||||
image: string;
|
||||
/** The points of the frame. */
|
||||
points: Array<SpriteCustomPointData>;
|
||||
/** The origin point. */
|
||||
originPoint: SpriteCustomPointData;
|
||||
/** The center of the frame. */
|
||||
centerPoint: SpriteCenterPointData;
|
||||
/** Is The collision mask custom? */
|
||||
hasCustomCollisionMask: boolean;
|
||||
/** The collision mask if it is custom. */
|
||||
customCollisionMask: Array<Array<SpritePoint>>;
|
||||
};
|
||||
|
||||
/** Represents the data of a {@link gdjs.SpriteAnimationDirection}. */
|
||||
export type SpriteDirectionData = {
|
||||
/** Time between each frame, in seconds. */
|
||||
timeBetweenFrames: float;
|
||||
/** Is the animation looping? */
|
||||
looping: boolean;
|
||||
/** The list of frames. */
|
||||
sprites: Array<SpriteFrameData>;
|
||||
};
|
||||
|
||||
/** Represents the data of a {@link gdjs.SpriteAnimation}. */
|
||||
export type SpriteAnimationData = {
|
||||
/** The name of the animation. */
|
||||
name: string;
|
||||
/** Does the animation use multiple {@link gdjs.SpriteAnimationDirection}? */
|
||||
useMultipleDirections: boolean;
|
||||
/** The list of {@link SpriteDirectionData} representing {@link gdjs.SpriteAnimationDirection} instances. */
|
||||
directions: Array<SpriteDirectionData>;
|
||||
};
|
||||
|
||||
/**
|
||||
* Abstraction from graphic libraries texture classes.
|
||||
*/
|
||||
export interface AnimationFrameTextureManager<T> {
|
||||
getAnimationFrameTexture(imageName: string): T;
|
||||
getAnimationFrameWidth(pixiTexture: T);
|
||||
getAnimationFrameHeight(pixiTexture: T);
|
||||
}
|
||||
|
||||
/**
|
||||
* A frame used by a SpriteAnimation in a {@link gdjs.SpriteRuntimeObject}.
|
||||
*
|
||||
* It contains the texture displayed as well as information like the points position
|
||||
* or the collision mask.
|
||||
*/
|
||||
export class SpriteAnimationFrame<T> {
|
||||
image: string;
|
||||
|
||||
//TODO: Rename in imageName, and do not store it in the object?
|
||||
texture: T;
|
||||
center: SpritePoint = { x: 0, y: 0 };
|
||||
origin: SpritePoint = { x: 0, y: 0 };
|
||||
hasCustomHitBoxes: boolean = false;
|
||||
customHitBoxes: gdjs.Polygon[] = [];
|
||||
points: Hashtable<SpritePoint>;
|
||||
|
||||
/**
|
||||
* @param imageManager The game image manager
|
||||
* @param frameData The frame data used to initialize the frame
|
||||
*/
|
||||
constructor(
|
||||
frameData: SpriteFrameData,
|
||||
textureManager: gdjs.AnimationFrameTextureManager<T>
|
||||
) {
|
||||
this.image = frameData ? frameData.image : '';
|
||||
this.texture = textureManager.getAnimationFrameTexture(this.image);
|
||||
this.points = new Hashtable();
|
||||
this.reinitialize(frameData, textureManager);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param frameData The frame data used to initialize the frame
|
||||
* @param textureManager The game image manager
|
||||
*/
|
||||
reinitialize(
|
||||
frameData: SpriteFrameData,
|
||||
textureManager: gdjs.AnimationFrameTextureManager<T>
|
||||
) {
|
||||
this.points.clear();
|
||||
for (let i = 0, len = frameData.points.length; i < len; ++i) {
|
||||
const ptData = frameData.points[i];
|
||||
const point = { x: ptData.x, y: ptData.y };
|
||||
this.points.put(ptData.name, point);
|
||||
}
|
||||
const origin = frameData.originPoint;
|
||||
this.origin.x = origin.x;
|
||||
this.origin.y = origin.y;
|
||||
const center = frameData.centerPoint;
|
||||
if (center.automatic !== true) {
|
||||
this.center.x = center.x;
|
||||
this.center.y = center.y;
|
||||
} else {
|
||||
this.center.x = textureManager.getAnimationFrameWidth(this.texture) / 2;
|
||||
this.center.y =
|
||||
textureManager.getAnimationFrameHeight(this.texture) / 2;
|
||||
}
|
||||
|
||||
//Load the custom collision mask, if any:
|
||||
if (frameData.hasCustomCollisionMask) {
|
||||
this.hasCustomHitBoxes = true;
|
||||
let i = 0;
|
||||
for (let len = frameData.customCollisionMask.length; i < len; ++i) {
|
||||
const polygonData: SpritePoint[] = frameData.customCollisionMask[i];
|
||||
|
||||
//Add a polygon, if necessary (Avoid recreating a polygon if it already exists).
|
||||
if (i >= this.customHitBoxes.length) {
|
||||
this.customHitBoxes.push(new gdjs.Polygon());
|
||||
}
|
||||
let j = 0;
|
||||
for (const len2 = polygonData.length; j < len2; ++j) {
|
||||
const pointData: SpritePoint = polygonData[j];
|
||||
|
||||
//Add a point, if necessary (Avoid recreating a point if it already exists).
|
||||
if (j >= this.customHitBoxes[i].vertices.length) {
|
||||
this.customHitBoxes[i].vertices.push([0, 0]);
|
||||
}
|
||||
this.customHitBoxes[i].vertices[j][0] = pointData.x;
|
||||
this.customHitBoxes[i].vertices[j][1] = pointData.y;
|
||||
}
|
||||
this.customHitBoxes[i].vertices.length = j;
|
||||
}
|
||||
this.customHitBoxes.length = i;
|
||||
} else {
|
||||
this.customHitBoxes.length = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a point of the frame.<br>
|
||||
* If the point does not exist, the origin is returned.
|
||||
* @param name The point's name
|
||||
* @return The requested point. If it doesn't exists returns the origin point.
|
||||
*/
|
||||
getPoint(name: string): SpritePoint {
|
||||
if (name === 'Centre' || name === 'Center') {
|
||||
return this.center;
|
||||
} else {
|
||||
if (name === 'Origin') {
|
||||
return this.origin;
|
||||
}
|
||||
}
|
||||
return this.points.containsKey(name)
|
||||
? this.points.get(name)
|
||||
: this.origin;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a direction of an animation of a {@link gdjs.SpriteRuntimeObject}.
|
||||
*/
|
||||
export class SpriteAnimationDirection<T> {
|
||||
timeBetweenFrames: float;
|
||||
loop: boolean;
|
||||
frames: SpriteAnimationFrame<T>[] = [];
|
||||
|
||||
/**
|
||||
* @param imageManager The game image manager
|
||||
* @param directionData The direction data used to initialize the direction
|
||||
*/
|
||||
constructor(
|
||||
directionData: SpriteDirectionData,
|
||||
textureManager: gdjs.AnimationFrameTextureManager<T>
|
||||
) {
|
||||
this.timeBetweenFrames = directionData
|
||||
? directionData.timeBetweenFrames
|
||||
: 1.0;
|
||||
this.loop = !!directionData.looping;
|
||||
this.reinitialize(directionData, textureManager);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param directionData The direction data used to initialize the direction
|
||||
* @param textureManager The game image manager
|
||||
*/
|
||||
reinitialize(
|
||||
directionData: SpriteDirectionData,
|
||||
textureManager: gdjs.AnimationFrameTextureManager<T>
|
||||
) {
|
||||
this.timeBetweenFrames = directionData
|
||||
? directionData.timeBetweenFrames
|
||||
: 1.0;
|
||||
this.loop = !!directionData.looping;
|
||||
let i = 0;
|
||||
for (const len = directionData.sprites.length; i < len; ++i) {
|
||||
const frameData = directionData.sprites[i];
|
||||
if (i < this.frames.length) {
|
||||
this.frames[i].reinitialize(frameData, textureManager);
|
||||
} else {
|
||||
this.frames.push(
|
||||
new gdjs.SpriteAnimationFrame<T>(frameData, textureManager)
|
||||
);
|
||||
}
|
||||
}
|
||||
this.frames.length = i;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an animation of a {@link SpriteRuntimeObject}.
|
||||
*/
|
||||
export class SpriteAnimation<T> {
|
||||
hasMultipleDirections: boolean;
|
||||
name: string;
|
||||
directions: gdjs.SpriteAnimationDirection<T>[] = [];
|
||||
|
||||
/**
|
||||
* @param animData The animation data used to initialize the animation
|
||||
* @param textureManager The game image manager
|
||||
*/
|
||||
constructor(
|
||||
animData: SpriteAnimationData,
|
||||
textureManager: gdjs.AnimationFrameTextureManager<T>
|
||||
) {
|
||||
this.hasMultipleDirections = !!animData.useMultipleDirections;
|
||||
this.name = animData.name || '';
|
||||
this.reinitialize(animData, textureManager);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param animData The animation data used to initialize the animation
|
||||
* @param textureManager The game image manager
|
||||
*/
|
||||
reinitialize(
|
||||
animData: SpriteAnimationData,
|
||||
textureManager: gdjs.AnimationFrameTextureManager<T>
|
||||
) {
|
||||
this.hasMultipleDirections = !!animData.useMultipleDirections;
|
||||
this.name = animData.name || '';
|
||||
let i = 0;
|
||||
for (const len = animData.directions.length; i < len; ++i) {
|
||||
const directionData = animData.directions[i];
|
||||
if (i < this.directions.length) {
|
||||
this.directions[i].reinitialize(directionData, textureManager);
|
||||
} else {
|
||||
this.directions.push(
|
||||
new gdjs.SpriteAnimationDirection(directionData, textureManager)
|
||||
);
|
||||
}
|
||||
}
|
||||
// Make sure to delete already existing directions which are not used anymore.
|
||||
this.directions.length = i;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Image-base animation model.
|
||||
*/
|
||||
export class SpriteAnimator<T> implements gdjs.Animatable {
|
||||
_animations: gdjs.SpriteAnimation<T>[] = [];
|
||||
_textureManager: gdjs.AnimationFrameTextureManager<T>;
|
||||
/**
|
||||
* Reference to the current SpriteAnimationFrame that is displayed.
|
||||
* Can be null, so ensure that this case is handled properly.
|
||||
*/
|
||||
private _animationFrame: gdjs.SpriteAnimationFrame<T> | null = null;
|
||||
private _animationFrameDirty: boolean = true;
|
||||
|
||||
private _currentAnimation: integer = 0;
|
||||
private _currentDirection: integer = 0;
|
||||
private _currentFrameIndex: integer = 0;
|
||||
/** In seconds */
|
||||
private _animationElapsedTime: float = 0;
|
||||
private _animationSpeedScale: float = 1;
|
||||
private _animationPaused: boolean = false;
|
||||
private _onFrameChange: (() => void) | null = null;
|
||||
|
||||
/**
|
||||
* @param frameData The frame data used to initialize the frame
|
||||
* @param textureManager The game image manager
|
||||
*/
|
||||
constructor(
|
||||
animations: Array<SpriteAnimationData>,
|
||||
textureManager: gdjs.AnimationFrameTextureManager<T>
|
||||
) {
|
||||
this._textureManager = textureManager;
|
||||
for (let i = 0, len = animations.length; i < len; ++i) {
|
||||
this._animations.push(
|
||||
new gdjs.SpriteAnimation(animations[i], textureManager)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
invalidateFrame() {
|
||||
this._animationFrameDirty = true;
|
||||
if (this._onFrameChange) {
|
||||
this._onFrameChange();
|
||||
}
|
||||
}
|
||||
|
||||
reinitialize(animations: Array<SpriteAnimationData>) {
|
||||
this._currentAnimation = 0;
|
||||
this._currentDirection = 0;
|
||||
this._currentFrameIndex = 0;
|
||||
this._animationElapsedTime = 0;
|
||||
this._animationSpeedScale = 1;
|
||||
this._animationPaused = false;
|
||||
|
||||
let i = 0;
|
||||
for (const len = animations.length; i < len; ++i) {
|
||||
const animData = animations[i];
|
||||
if (i < this._animations.length) {
|
||||
this._animations[i].reinitialize(animData, this._textureManager);
|
||||
} else {
|
||||
this._animations.push(
|
||||
new gdjs.SpriteAnimation(animData, this._textureManager)
|
||||
);
|
||||
}
|
||||
}
|
||||
this._animations.length = i;
|
||||
|
||||
// Make sure to delete already existing animations which are not used anymore.
|
||||
this._animationFrame = null;
|
||||
this.invalidateFrame();
|
||||
}
|
||||
|
||||
updateFromObjectData(
|
||||
oldAnimations: Array<SpriteAnimationData>,
|
||||
newAnimations: Array<SpriteAnimationData>
|
||||
): boolean {
|
||||
let i = 0;
|
||||
for (const len = newAnimations.length; i < len; ++i) {
|
||||
const animData = newAnimations[i];
|
||||
if (i < this._animations.length) {
|
||||
this._animations[i].reinitialize(animData, this._textureManager);
|
||||
} else {
|
||||
this._animations.push(
|
||||
new gdjs.SpriteAnimation(animData, this._textureManager)
|
||||
);
|
||||
}
|
||||
}
|
||||
this._animations.length = i;
|
||||
|
||||
// Make sure to delete already existing animations which are not used anymore.
|
||||
this.invalidateFrame();
|
||||
const animationFrame = this.getCurrentFrame();
|
||||
if (!animationFrame) {
|
||||
this.setAnimationIndex(0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns Returns the current frame or null if the current animation doesn't have any frame.
|
||||
*/
|
||||
getCurrentFrame(): gdjs.SpriteAnimationFrame<T> | null {
|
||||
if (!this._animationFrameDirty) {
|
||||
return this._animationFrame;
|
||||
}
|
||||
this._animationFrameDirty = false;
|
||||
if (
|
||||
this._currentAnimation < this._animations.length &&
|
||||
this._currentDirection <
|
||||
this._animations[this._currentAnimation].directions.length
|
||||
) {
|
||||
const direction = this._animations[this._currentAnimation].directions[
|
||||
this._currentDirection
|
||||
];
|
||||
if (this._currentFrameIndex < direction.frames.length) {
|
||||
this._animationFrame = direction.frames[this._currentFrameIndex];
|
||||
return this._animationFrame;
|
||||
}
|
||||
}
|
||||
|
||||
//Invalid animation/direction/frame:
|
||||
this._animationFrame = null;
|
||||
return this._animationFrame;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the current frame of the object according to the elapsed time on the scene.
|
||||
* @param timeDelta in seconds
|
||||
*/
|
||||
step(timeDelta: float): boolean {
|
||||
if (
|
||||
this._currentAnimation >= this._animations.length ||
|
||||
this._currentDirection >=
|
||||
this._animations[this._currentAnimation].directions.length
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
const direction = this._animations[this._currentAnimation].directions[
|
||||
this._currentDirection
|
||||
];
|
||||
const animationDuration = this.getAnimationDuration();
|
||||
if (
|
||||
!this._animationPaused &&
|
||||
(direction.loop || this._animationElapsedTime !== animationDuration) &&
|
||||
direction.timeBetweenFrames
|
||||
) {
|
||||
const animationElapsedTime =
|
||||
this._animationElapsedTime + timeDelta * this._animationSpeedScale;
|
||||
return this.setAnimationElapsedTime(
|
||||
direction.loop
|
||||
? gdjs.evtTools.common.mod(animationElapsedTime, animationDuration)
|
||||
: gdjs.evtTools.common.clamp(
|
||||
animationElapsedTime,
|
||||
0,
|
||||
animationDuration
|
||||
)
|
||||
);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a listener to frame changes.
|
||||
*
|
||||
* It's useful for custom objects as they don't drive this class themselves.
|
||||
*
|
||||
* @param callback Called each time {@link getCurrentFrame} changes.
|
||||
*/
|
||||
setOnFrameChangeCallback(callback: () => void): void {
|
||||
this._onFrameChange = callback;
|
||||
}
|
||||
|
||||
getAnimationIndex(): integer {
|
||||
return this._currentAnimation;
|
||||
}
|
||||
|
||||
setAnimationIndex(newAnimation: integer): boolean {
|
||||
// Truncate the index.
|
||||
newAnimation = newAnimation | 0;
|
||||
if (
|
||||
newAnimation < this._animations.length &&
|
||||
this._currentAnimation !== newAnimation &&
|
||||
newAnimation >= 0
|
||||
) {
|
||||
this._currentAnimation = newAnimation;
|
||||
this._currentFrameIndex = 0;
|
||||
this._animationElapsedTime = 0;
|
||||
this.invalidateFrame();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
getAnimationName(): string {
|
||||
if (this._currentAnimation >= this._animations.length) {
|
||||
return '';
|
||||
}
|
||||
return this._animations[this._currentAnimation].name;
|
||||
}
|
||||
|
||||
setAnimationName(newAnimationName: string): boolean {
|
||||
if (!newAnimationName) {
|
||||
return false;
|
||||
}
|
||||
for (let i = 0; i < this._animations.length; ++i) {
|
||||
if (this._animations[i].name === newAnimationName) {
|
||||
this.setAnimationIndex(i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
hasAnimationEnded(): boolean {
|
||||
if (
|
||||
this._currentAnimation >= this._animations.length ||
|
||||
this._currentDirection >=
|
||||
this._animations[this._currentAnimation].directions.length
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
const direction = this._animations[this._currentAnimation].directions[
|
||||
this._currentDirection
|
||||
];
|
||||
if (direction.loop) {
|
||||
return false;
|
||||
}
|
||||
return (
|
||||
this._currentFrameIndex === direction.frames.length - 1 &&
|
||||
this._animationElapsedTime ===
|
||||
direction.frames.length * direction.timeBetweenFrames
|
||||
);
|
||||
}
|
||||
|
||||
isAnimationPaused() {
|
||||
return this._animationPaused;
|
||||
}
|
||||
|
||||
pauseAnimation() {
|
||||
this._animationPaused = true;
|
||||
}
|
||||
|
||||
resumeAnimation() {
|
||||
this._animationPaused = false;
|
||||
}
|
||||
|
||||
getAnimationSpeedScale() {
|
||||
return this._animationSpeedScale;
|
||||
}
|
||||
|
||||
setAnimationSpeedScale(ratio: float): void {
|
||||
this._animationSpeedScale = ratio;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the current frame displayed by the animation
|
||||
* @param newFrameIndex The index of the frame to be displayed
|
||||
*/
|
||||
setAnimationFrameIndex(newFrameIndex: integer): boolean {
|
||||
if (
|
||||
this._currentAnimation >= this._animations.length ||
|
||||
this._currentDirection >=
|
||||
this._animations[this._currentAnimation].directions.length
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
const direction = this._animations[this._currentAnimation].directions[
|
||||
this._currentDirection
|
||||
];
|
||||
if (
|
||||
newFrameIndex >= 0 &&
|
||||
newFrameIndex < direction.frames.length &&
|
||||
newFrameIndex !== this._currentFrameIndex
|
||||
) {
|
||||
this._currentFrameIndex = newFrameIndex;
|
||||
this._animationElapsedTime =
|
||||
newFrameIndex * direction.timeBetweenFrames;
|
||||
this.invalidateFrame();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the index of the current frame displayed by the animation
|
||||
* @return newFrame The index of the frame being displayed
|
||||
*/
|
||||
getAnimationFrameIndex(): integer {
|
||||
return this._currentFrameIndex;
|
||||
}
|
||||
|
||||
getAnimationElapsedTime(): float {
|
||||
return this._animationElapsedTime;
|
||||
}
|
||||
|
||||
setAnimationElapsedTime(time: float): boolean {
|
||||
const direction = this._animations[this._currentAnimation].directions[
|
||||
this._currentDirection
|
||||
];
|
||||
this._animationElapsedTime = gdjs.evtTools.common.clamp(
|
||||
time,
|
||||
0,
|
||||
this.getAnimationDuration()
|
||||
);
|
||||
|
||||
const oldFrame = this._currentFrameIndex;
|
||||
this._currentFrameIndex = Math.min(
|
||||
Math.floor(this._animationElapsedTime / direction.timeBetweenFrames),
|
||||
direction.frames.length - 1
|
||||
);
|
||||
if (oldFrame !== this._currentFrameIndex) {
|
||||
this.invalidateFrame();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
getAnimationDuration(): float {
|
||||
const direction = this._animations[this._currentAnimation].directions[
|
||||
this._currentDirection
|
||||
];
|
||||
return direction.frames.length * direction.timeBetweenFrames;
|
||||
}
|
||||
|
||||
getAnimationFrameCount(): integer {
|
||||
if (this._currentAnimation >= this._animations.length) {
|
||||
return 0;
|
||||
}
|
||||
const currentAnimation = this._animations[this._currentAnimation];
|
||||
if (this._currentDirection >= currentAnimation.directions.length) {
|
||||
return 0;
|
||||
}
|
||||
return currentAnimation.directions[this._currentDirection].frames.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the angle (or direction index) of the object
|
||||
* @param The new angle (or direction index) to be applied
|
||||
* @deprecated
|
||||
*/
|
||||
setDirectionOrAngle(oldValue: float, newValue: float): float | null {
|
||||
if (this._currentAnimation >= this._animations.length) {
|
||||
return null;
|
||||
}
|
||||
const anim = this._animations[this._currentAnimation];
|
||||
if (!anim.hasMultipleDirections) {
|
||||
return oldValue === newValue ? null : newValue;
|
||||
} else {
|
||||
newValue = newValue | 0;
|
||||
if (
|
||||
newValue === this._currentDirection ||
|
||||
newValue >= anim.directions.length ||
|
||||
anim.directions[newValue].frames.length === 0
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
this._currentDirection = newValue;
|
||||
this._currentFrameIndex = 0;
|
||||
this._animationElapsedTime = 0;
|
||||
this.invalidateFrame();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
getDirectionOrAngle(angle: float): float {
|
||||
if (this._currentAnimation >= this._animations.length) {
|
||||
return 0;
|
||||
}
|
||||
if (!this._animations[this._currentAnimation].hasMultipleDirections) {
|
||||
return angle;
|
||||
} else {
|
||||
return this._currentDirection;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
getAngle(angle: float): float {
|
||||
if (this._currentAnimation >= this._animations.length) {
|
||||
return 0;
|
||||
}
|
||||
if (!this._animations[this._currentAnimation].hasMultipleDirections) {
|
||||
return angle;
|
||||
} else {
|
||||
return this._currentDirection * 45;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
setAngle(oldAngle: float, angle: float): float | null {
|
||||
if (this._currentAnimation >= this._animations.length) {
|
||||
return null;
|
||||
}
|
||||
if (!this._animations[this._currentAnimation].hasMultipleDirections) {
|
||||
if (oldAngle === angle) {
|
||||
return null;
|
||||
}
|
||||
return angle;
|
||||
} else {
|
||||
angle = angle % 360;
|
||||
if (angle < 0) {
|
||||
angle += 360;
|
||||
}
|
||||
return this.setDirectionOrAngle(oldAngle, Math.round(angle / 45) % 8);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* Return true if animation has ended.
|
||||
* Prefer using {@link hasAnimationEnded}. This method returns true as soon as
|
||||
* the animation enters the last frame, not at the end of the last frame.
|
||||
*/
|
||||
hasAnimationEndedLegacy(): boolean {
|
||||
if (
|
||||
this._currentAnimation >= this._animations.length ||
|
||||
this._currentDirection >=
|
||||
this._animations[this._currentAnimation].directions.length
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
const direction = this._animations[this._currentAnimation].directions[
|
||||
this._currentDirection
|
||||
];
|
||||
if (direction.loop) {
|
||||
return false;
|
||||
}
|
||||
return this._currentFrameIndex === direction.frames.length - 1;
|
||||
}
|
||||
}
|
||||
}
|
@@ -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
|
||||
|
@@ -152,6 +152,14 @@ namespace gdjs {
|
||||
this._pixiContainer.removeChild(layerPixiObject);
|
||||
this._pixiContainer.addChildAt(layerPixiObject, index);
|
||||
}
|
||||
|
||||
static getAnimationFrameTextureManager(
|
||||
imageManager: gdjs.PixiImageManager
|
||||
) {
|
||||
return gdjs.SpriteRuntimeObjectPixiRenderer.getAnimationFrameTextureManager(
|
||||
imageManager
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Register the class to let the engine use it.
|
||||
|
@@ -264,9 +264,10 @@ namespace gdjs {
|
||||
|
||||
// Draw custom point
|
||||
if (showCustomPoints && object instanceof gdjs.SpriteRuntimeObject) {
|
||||
if (!object._animationFrame) continue;
|
||||
const animationFrame = object._animator.getCurrentFrame();
|
||||
if (!animationFrame) continue;
|
||||
|
||||
for (const customPointName in object._animationFrame.points.items) {
|
||||
for (const customPointName in animationFrame.points.items) {
|
||||
let customPoint = object.getPointPosition(customPointName);
|
||||
|
||||
customPoint = layer.applyLayerTransformation(
|
||||
|
@@ -228,7 +228,7 @@ namespace gdjs {
|
||||
useTransparentTexture,
|
||||
forceBasicMaterial,
|
||||
}: { useTransparentTexture: boolean; forceBasicMaterial: boolean }
|
||||
) {
|
||||
): THREE.Material {
|
||||
const cacheKey = `${resourceName}|${useTransparentTexture ? 1 : 0}|${
|
||||
forceBasicMaterial ? 1 : 0
|
||||
}`;
|
||||
|
@@ -1,4 +1,7 @@
|
||||
namespace gdjs {
|
||||
export interface PixiImageManager {
|
||||
_pixiAnimationFrameTextureManager: PixiAnimationFrameTextureManager;
|
||||
}
|
||||
/**
|
||||
* The renderer for a gdjs.SpriteRuntimeObject using Pixi.js.
|
||||
*/
|
||||
@@ -19,9 +22,8 @@ namespace gdjs {
|
||||
instanceContainer: gdjs.RuntimeInstanceContainer
|
||||
) {
|
||||
this._object = runtimeObject;
|
||||
this._sprite = new PIXI.Sprite(
|
||||
instanceContainer.getGame().getImageManager().getInvalidPIXITexture()
|
||||
);
|
||||
const imageManager = instanceContainer.getGame().getImageManager();
|
||||
this._sprite = new PIXI.Sprite(imageManager.getInvalidPIXITexture());
|
||||
const layer = instanceContainer.getLayer('');
|
||||
if (layer) {
|
||||
layer
|
||||
@@ -54,22 +56,19 @@ namespace gdjs {
|
||||
* Update the internal PIXI.Sprite position, angle...
|
||||
*/
|
||||
_updatePIXISprite() {
|
||||
if (this._object._animationFrame !== null) {
|
||||
const animationFrame = this._object._animator.getCurrentFrame();
|
||||
if (animationFrame !== null) {
|
||||
this._sprite.anchor.x =
|
||||
this._object._animationFrame.center.x /
|
||||
this._sprite.texture.frame.width;
|
||||
animationFrame.center.x / this._sprite.texture.frame.width;
|
||||
this._sprite.anchor.y =
|
||||
this._object._animationFrame.center.y /
|
||||
this._sprite.texture.frame.height;
|
||||
animationFrame.center.y / this._sprite.texture.frame.height;
|
||||
this._sprite.position.x =
|
||||
this._object.x +
|
||||
(this._object._animationFrame.center.x -
|
||||
this._object._animationFrame.origin.x) *
|
||||
(animationFrame.center.x - animationFrame.origin.x) *
|
||||
Math.abs(this._object._scaleX);
|
||||
this._sprite.position.y =
|
||||
this._object.y +
|
||||
(this._object._animationFrame.center.y -
|
||||
this._object._animationFrame.origin.y) *
|
||||
(animationFrame.center.y - animationFrame.origin.y) *
|
||||
Math.abs(this._object._scaleY);
|
||||
this._sprite.rotation = gdjs.toRad(this._object.angle);
|
||||
this._sprite.visible = !this._object.hidden;
|
||||
@@ -100,7 +99,7 @@ namespace gdjs {
|
||||
/**
|
||||
* Update the internal texture of the PIXI sprite.
|
||||
*/
|
||||
updateFrame(animationFrame): void {
|
||||
updateFrame(animationFrame: gdjs.SpriteAnimationFrame<PIXI.Texture>): void {
|
||||
this._spriteDirty = true;
|
||||
this._sprite.texture = animationFrame.texture;
|
||||
}
|
||||
@@ -110,8 +109,9 @@ namespace gdjs {
|
||||
}
|
||||
|
||||
updateX(): void {
|
||||
const animationFrame = this._object
|
||||
._animationFrame as SpriteAnimationFrame;
|
||||
const animationFrame = this._object._animator.getCurrentFrame() as SpriteAnimationFrame<
|
||||
PIXI.Texture
|
||||
>;
|
||||
this._sprite.position.x =
|
||||
this._object.x +
|
||||
(animationFrame.center.x - animationFrame.origin.x) *
|
||||
@@ -119,8 +119,9 @@ namespace gdjs {
|
||||
}
|
||||
|
||||
updateY(): void {
|
||||
const animationFrame = this._object
|
||||
._animationFrame as SpriteAnimationFrame;
|
||||
const animationFrame = this._object._animator.getCurrentFrame() as SpriteAnimationFrame<
|
||||
PIXI.Texture
|
||||
>;
|
||||
this._sprite.position.y =
|
||||
this._object.y +
|
||||
(animationFrame.center.y - animationFrame.origin.y) *
|
||||
@@ -184,18 +185,35 @@ namespace gdjs {
|
||||
return this._sprite.texture.frame.height;
|
||||
}
|
||||
|
||||
static getAnimationFrame(
|
||||
imageManager: gdjs.PixiImageManager,
|
||||
imageName: string
|
||||
) {
|
||||
return imageManager.getPIXITexture(imageName);
|
||||
static getAnimationFrameTextureManager(
|
||||
imageManager: gdjs.PixiImageManager
|
||||
): PixiAnimationFrameTextureManager {
|
||||
if (!imageManager._pixiAnimationFrameTextureManager) {
|
||||
imageManager._pixiAnimationFrameTextureManager = new PixiAnimationFrameTextureManager(
|
||||
imageManager
|
||||
);
|
||||
}
|
||||
return imageManager._pixiAnimationFrameTextureManager;
|
||||
}
|
||||
}
|
||||
|
||||
class PixiAnimationFrameTextureManager
|
||||
implements gdjs.AnimationFrameTextureManager<PIXI.Texture> {
|
||||
private _imageManager: gdjs.PixiImageManager;
|
||||
|
||||
constructor(imageManager: gdjs.PixiImageManager) {
|
||||
this._imageManager = imageManager;
|
||||
}
|
||||
|
||||
static getAnimationFrameWidth(pixiTexture: PIXI.Texture) {
|
||||
getAnimationFrameTexture(imageName: string) {
|
||||
return this._imageManager.getPIXITexture(imageName);
|
||||
}
|
||||
|
||||
getAnimationFrameWidth(pixiTexture: PIXI.Texture) {
|
||||
return pixiTexture.width;
|
||||
}
|
||||
|
||||
static getAnimationFrameHeight(pixiTexture: PIXI.Texture) {
|
||||
getAnimationFrameHeight(pixiTexture: PIXI.Texture) {
|
||||
return pixiTexture.height;
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -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"
|
||||
}
|
||||
}
|
||||
|
@@ -70,6 +70,7 @@ module.exports = function (config) {
|
||||
'./newIDE/app/resources/GDJS/Runtime/variablescontainer.js',
|
||||
'./newIDE/app/resources/GDJS/Runtime/oncetriggers.js',
|
||||
'./newIDE/app/resources/GDJS/Runtime/runtimebehavior.js',
|
||||
'./newIDE/app/resources/GDJS/Runtime/SpriteAnimator.js',
|
||||
'./newIDE/app/resources/GDJS/Runtime/spriteruntimeobject.js',
|
||||
'./newIDE/app/resources/GDJS/Runtime/CustomRuntimeObject.js',
|
||||
'./newIDE/app/resources/GDJS/Runtime/CustomRuntimeObject2D.js',
|
||||
|
@@ -202,7 +202,7 @@ describe('gdjs.SpriteRuntimeObject', () => {
|
||||
|
||||
runtimeScene.renderAndStep(stepDurationInMilliseconds);
|
||||
|
||||
expect(object._animationElapsedTime).to.be(
|
||||
expect(object.getAnimationElapsedTime()).to.be(
|
||||
stepDurationInMilliseconds / 1000
|
||||
);
|
||||
|
||||
@@ -232,7 +232,7 @@ describe('gdjs.SpriteRuntimeObject', () => {
|
||||
}
|
||||
|
||||
// Almost at the animation end.
|
||||
expect(object._animationElapsedTime).to.be.within(
|
||||
expect(object.getAnimationElapsedTime()).to.be.within(
|
||||
3 * firstAnimationTimeBetweenFrames - stepDurationInMilliseconds / 1000,
|
||||
3 * firstAnimationTimeBetweenFrames - 0.001
|
||||
);
|
||||
@@ -241,7 +241,7 @@ describe('gdjs.SpriteRuntimeObject', () => {
|
||||
runtimeScene.renderAndStep(stepDurationInMilliseconds);
|
||||
|
||||
// The animation ended.
|
||||
expect(object._animationElapsedTime).to.be(
|
||||
expect(object.getAnimationElapsedTime()).to.be(
|
||||
3 * firstAnimationTimeBetweenFrames
|
||||
);
|
||||
expect(object.getAnimationFrame()).to.be(2);
|
||||
@@ -249,7 +249,7 @@ describe('gdjs.SpriteRuntimeObject', () => {
|
||||
runtimeScene.renderAndStep(stepDurationInMilliseconds);
|
||||
|
||||
// No change.
|
||||
expect(object._animationElapsedTime).to.be(
|
||||
expect(object.getAnimationElapsedTime()).to.be(
|
||||
3 * firstAnimationTimeBetweenFrames
|
||||
);
|
||||
expect(object.getAnimationFrame()).to.be(2);
|
||||
@@ -272,7 +272,7 @@ describe('gdjs.SpriteRuntimeObject', () => {
|
||||
}
|
||||
|
||||
// Almost at the animation end.
|
||||
expect(object._animationElapsedTime).to.be.within(
|
||||
expect(object.getAnimationElapsedTime()).to.be.within(
|
||||
3 * firstAnimationTimeBetweenFrames - stepDurationInMilliseconds / 1000,
|
||||
3 * firstAnimationTimeBetweenFrames - 0.001
|
||||
);
|
||||
@@ -281,7 +281,7 @@ describe('gdjs.SpriteRuntimeObject', () => {
|
||||
runtimeScene.renderAndStep(stepDurationInMilliseconds);
|
||||
|
||||
// The animation looped to the beginning.
|
||||
expect(object._animationElapsedTime).to.within(0.01, 0.02);
|
||||
expect(object.getAnimationElapsedTime()).to.within(0.01, 0.02);
|
||||
expect(object.getAnimationFrame()).to.be(0);
|
||||
});
|
||||
});
|
||||
@@ -302,7 +302,7 @@ describe('gdjs.SpriteRuntimeObject', () => {
|
||||
|
||||
runtimeScene.renderAndStep(stepDurationInMilliseconds);
|
||||
|
||||
expect(object._animationElapsedTime).to.be(
|
||||
expect(object.getAnimationElapsedTime()).to.be(
|
||||
2 * firstAnimationTimeBetweenFrames - stepDurationInMilliseconds / 1000
|
||||
);
|
||||
expect(object.getAnimationFrame()).to.be(1);
|
||||
@@ -326,7 +326,7 @@ describe('gdjs.SpriteRuntimeObject', () => {
|
||||
}
|
||||
|
||||
// Almost at the animation beginning.
|
||||
expect(object._animationElapsedTime).to.be.within(
|
||||
expect(object.getAnimationElapsedTime()).to.be.within(
|
||||
0.001,
|
||||
stepDurationInMilliseconds / 60
|
||||
);
|
||||
@@ -335,13 +335,13 @@ describe('gdjs.SpriteRuntimeObject', () => {
|
||||
runtimeScene.renderAndStep(stepDurationInMilliseconds);
|
||||
|
||||
// Reached the animation beginning.
|
||||
expect(object._animationElapsedTime).to.be(0);
|
||||
expect(object.getAnimationElapsedTime()).to.be(0);
|
||||
expect(object.getAnimationFrame()).to.be(0);
|
||||
|
||||
runtimeScene.renderAndStep(stepDurationInMilliseconds);
|
||||
|
||||
// No change.
|
||||
expect(object._animationElapsedTime).to.be(0);
|
||||
expect(object.getAnimationElapsedTime()).to.be(0);
|
||||
expect(object.getAnimationFrame()).to.be(0);
|
||||
});
|
||||
|
||||
@@ -364,7 +364,7 @@ describe('gdjs.SpriteRuntimeObject', () => {
|
||||
}
|
||||
|
||||
// Almost at the animation beginning.
|
||||
expect(object._animationElapsedTime).to.be.within(
|
||||
expect(object.getAnimationElapsedTime()).to.be.within(
|
||||
0.001,
|
||||
stepDurationInMilliseconds / 60
|
||||
);
|
||||
@@ -373,7 +373,7 @@ describe('gdjs.SpriteRuntimeObject', () => {
|
||||
runtimeScene.renderAndStep(stepDurationInMilliseconds);
|
||||
|
||||
// Reached the animation beginning.
|
||||
expect(object._animationElapsedTime).to.be.within(
|
||||
expect(object.getAnimationElapsedTime()).to.be.within(
|
||||
3 * firstAnimationTimeBetweenFrames - 0.004,
|
||||
3 * firstAnimationTimeBetweenFrames - 0.003
|
||||
);
|
||||
@@ -395,16 +395,16 @@ describe('gdjs.SpriteRuntimeObject', () => {
|
||||
|
||||
runtimeScene.renderAndStep(stepDurationInMilliseconds);
|
||||
|
||||
expect(object._animationElapsedTime).to.not.be(0);
|
||||
expect(object.getAnimationElapsedTime()).to.not.be(0);
|
||||
|
||||
object.setAnimation(1);
|
||||
|
||||
expect(object.getAnimationFrame()).to.be(0);
|
||||
expect(object._animationElapsedTime).to.be(0);
|
||||
expect(object.getAnimationElapsedTime()).to.be(0);
|
||||
|
||||
runtimeScene.renderAndStep(stepDurationInMilliseconds);
|
||||
|
||||
expect(object._animationElapsedTime).to.not.be(0);
|
||||
expect(object.getAnimationElapsedTime()).to.not.be(0);
|
||||
});
|
||||
|
||||
it('should reset the elapsed time on a frame when changing animation frame', () => {
|
||||
@@ -420,18 +420,18 @@ describe('gdjs.SpriteRuntimeObject', () => {
|
||||
|
||||
runtimeScene.renderAndStep(stepDurationInMilliseconds);
|
||||
|
||||
expect(object._animationElapsedTime).to.not.be(0);
|
||||
expect(object.getAnimationElapsedTime()).to.not.be(0);
|
||||
|
||||
object.setAnimationFrame(2);
|
||||
|
||||
expect(object.getAnimationFrame()).to.be(2);
|
||||
expect(object._animationElapsedTime).to.be(
|
||||
expect(object.getAnimationElapsedTime()).to.be(
|
||||
2 * firstAnimationTimeBetweenFrames
|
||||
);
|
||||
|
||||
runtimeScene.renderAndStep(stepDurationInMilliseconds);
|
||||
|
||||
expect(object._animationElapsedTime).to.not.be(0);
|
||||
expect(object.getAnimationElapsedTime()).to.not.be(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -772,6 +772,8 @@ interface CustomObjectConfiguration {
|
||||
|
||||
[Value] MapStringPropertyDescriptor GetInitialInstanceProperties([Const, Ref] InitialInstance instance, [Ref] Project project, [Ref] Layout scene);
|
||||
boolean UpdateInitialInstanceProperty([Ref] InitialInstance instance, [Const] DOMString name, [Const] DOMString value, [Ref] Project project, [Ref] Layout scene);
|
||||
|
||||
[Ref] SpriteAnimationList GetAnimations();
|
||||
};
|
||||
CustomObjectConfiguration implements ObjectConfiguration;
|
||||
|
||||
@@ -1173,6 +1175,8 @@ interface InitialInstance {
|
||||
void SetLocked(boolean lock);
|
||||
boolean IsSealed();
|
||||
void SetSealed(boolean seal);
|
||||
boolean ShouldKeepRatio();
|
||||
void SetShouldKeepRatio(boolean keepRatio);
|
||||
long GetZOrder();
|
||||
void SetZOrder(long zOrder);
|
||||
[Const, Ref] DOMString GetLayer();
|
||||
@@ -1386,8 +1390,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 +1441,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 +1506,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 +1528,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);
|
||||
@@ -1853,7 +1857,7 @@ interface BehaviorMetadata {
|
||||
|
||||
[Ref] Behavior Get();
|
||||
BehaviorsSharedData GetSharedDataInstance();
|
||||
|
||||
|
||||
[Value] MapStringPropertyDescriptor GetProperties();
|
||||
[Value] MapStringPropertyDescriptor GetSharedProperties();
|
||||
};
|
||||
@@ -2790,6 +2794,10 @@ interface EventsBasedObject {
|
||||
|
||||
[Ref] EventsBasedObject MarkAsRenderedIn3D(boolean isRenderedIn3D);
|
||||
boolean IsRenderedIn3D();
|
||||
[Ref] EventsBasedObject MarkAsAnimatable(boolean isAnimatable);
|
||||
boolean IsAnimatable();
|
||||
[Ref] EventsBasedObject MarkAsTextContainer(boolean isTextContainer);
|
||||
boolean IsTextContainer();
|
||||
|
||||
[Const, Value] DOMString STATIC_GetPropertyActionName([Const] DOMString propertyName);
|
||||
[Const, Value] DOMString STATIC_GetPropertyConditionName([Const] DOMString propertyName);
|
||||
@@ -3169,8 +3177,8 @@ interface Animation {
|
||||
void SetUseMultipleDirections(boolean enable);
|
||||
};
|
||||
|
||||
interface SpriteObject {
|
||||
void SpriteObject();
|
||||
interface SpriteAnimationList {
|
||||
void SpriteAnimationList();
|
||||
|
||||
void AddAnimation([Const, Ref] Animation animation);
|
||||
[Ref] Animation GetAnimation(unsigned long index);
|
||||
@@ -3181,12 +3189,18 @@ interface SpriteObject {
|
||||
void SwapAnimations(unsigned long first, unsigned long second);
|
||||
void MoveAnimation(unsigned long oldIndex, unsigned long newIndex);
|
||||
|
||||
void SetUpdateIfNotVisible(boolean updateIfNotVisible);
|
||||
boolean GetUpdateIfNotVisible();
|
||||
|
||||
boolean AdaptCollisionMaskAutomatically();
|
||||
void SetAdaptCollisionMaskAutomatically(boolean adaptCollisionMaskAutomatically);
|
||||
};
|
||||
|
||||
interface SpriteObject {
|
||||
void SpriteObject();
|
||||
|
||||
[Ref] SpriteAnimationList GetAnimations();
|
||||
|
||||
void SetUpdateIfNotVisible(boolean updateIfNotVisible);
|
||||
boolean GetUpdateIfNotVisible();
|
||||
};
|
||||
SpriteObject implements ObjectConfiguration;
|
||||
|
||||
interface Model3DAnimation {
|
||||
@@ -3608,7 +3622,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']\"")
|
||||
|
||||
|
@@ -1522,7 +1522,7 @@ describe('libGD.js', function () {
|
||||
anim1.setDirectionsCount(1);
|
||||
anim1.getDirection(0).addSprite(sprite1);
|
||||
|
||||
gd.castObject(obj.getConfiguration(), gd.SpriteObject).addAnimation(
|
||||
gd.castObject(obj.getConfiguration(), gd.SpriteObject).getAnimations().addAnimation(
|
||||
anim1
|
||||
);
|
||||
|
||||
@@ -1589,7 +1589,7 @@ describe('libGD.js', function () {
|
||||
const animation = new gd.Animation();
|
||||
animation.setDirectionsCount(1);
|
||||
animation.getDirection(0).addSprite(sprite1);
|
||||
spriteConfiguration.addAnimation(animation);
|
||||
spriteConfiguration.getAnimations().addAnimation(animation);
|
||||
|
||||
let worker = extend(new gd.ArbitraryResourceWorkerJS(project.getResourcesManager()), {
|
||||
exposeImage: function (image) {
|
||||
@@ -1620,7 +1620,7 @@ describe('libGD.js', function () {
|
||||
animation.getDirection(0).addSprite(sprite1);
|
||||
animation.getDirection(0).addSprite(sprite2);
|
||||
animation.getDirection(0).addSprite(sprite1);
|
||||
spriteObject.addAnimation(animation);
|
||||
spriteObject.getAnimations().addAnimation(animation);
|
||||
|
||||
const spriteObject2 = new gd.SpriteObject();
|
||||
const animation2 = new gd.Animation();
|
||||
@@ -1628,7 +1628,7 @@ describe('libGD.js', function () {
|
||||
animation2.getDirection(0).addSprite(sprite1);
|
||||
animation2.getDirection(0).addSprite(sprite3);
|
||||
animation2.getDirection(0).addSprite(sprite1);
|
||||
spriteObject2.addAnimation(animation2);
|
||||
spriteObject2.getAnimations().addAnimation(animation2);
|
||||
|
||||
const resourcesInUse = new gd.ResourcesInUseHelper();
|
||||
|
||||
@@ -1681,7 +1681,7 @@ describe('libGD.js', function () {
|
||||
animation.getDirection(0).addSprite(sprite1);
|
||||
animation.getDirection(0).addSprite(sprite2);
|
||||
animation.getDirection(0).addSprite(sprite1);
|
||||
spriteObject.addAnimation(animation);
|
||||
spriteObject.getAnimations().addAnimation(animation);
|
||||
|
||||
const object2 = project.insertNewObject(
|
||||
project,
|
||||
@@ -1697,7 +1697,7 @@ describe('libGD.js', function () {
|
||||
animation2.getDirection(0).addSprite(sprite1);
|
||||
animation2.getDirection(0).addSprite(sprite3);
|
||||
animation2.getDirection(0).addSprite(sprite1);
|
||||
spriteObject2.addAnimation(animation2);
|
||||
spriteObject2.getAnimations().addAnimation(animation2);
|
||||
|
||||
{
|
||||
const objectsCollector = new gd.ObjectsUsingResourceCollector(project.getResourcesManager(), 'Image1');
|
||||
@@ -3047,17 +3047,19 @@ describe('libGD.js', function () {
|
||||
});
|
||||
|
||||
it('can have animations', function () {
|
||||
let obj = new gd.SpriteObject();
|
||||
obj.addAnimation(new gd.Animation());
|
||||
obj.addAnimation(new gd.Animation());
|
||||
expect(obj.getAnimationsCount()).toBe(2);
|
||||
obj.removeAnimation(1);
|
||||
expect(obj.getAnimationsCount()).toBe(1);
|
||||
const obj = new gd.SpriteObject();
|
||||
const animations = obj.getAnimations();
|
||||
animations.addAnimation(new gd.Animation());
|
||||
animations.addAnimation(new gd.Animation());
|
||||
expect(animations.getAnimationsCount()).toBe(2);
|
||||
animations.removeAnimation(1);
|
||||
expect(animations.getAnimationsCount()).toBe(1);
|
||||
});
|
||||
|
||||
it('can swap animations', function () {
|
||||
let obj = new gd.SpriteObject();
|
||||
obj.removeAllAnimations();
|
||||
const obj = new gd.SpriteObject();
|
||||
const animations = obj.getAnimations();
|
||||
animations.removeAllAnimations();
|
||||
let anim1 = new gd.Animation();
|
||||
let anim2 = new gd.Animation();
|
||||
let sprite1 = new gd.Sprite();
|
||||
@@ -3071,14 +3073,14 @@ describe('libGD.js', function () {
|
||||
anim1.getDirection(0).addSprite(sprite1);
|
||||
anim2.getDirection(0).addSprite(sprite2);
|
||||
|
||||
obj.addAnimation(anim1);
|
||||
obj.addAnimation(anim2);
|
||||
animations.addAnimation(anim1);
|
||||
animations.addAnimation(anim2);
|
||||
expect(
|
||||
obj.getAnimation(0).getDirection(0).getSprite(0).getImageName()
|
||||
animations.getAnimation(0).getDirection(0).getSprite(0).getImageName()
|
||||
).toBe('image1');
|
||||
obj.swapAnimations(0, 1);
|
||||
animations.swapAnimations(0, 1);
|
||||
expect(
|
||||
obj.getAnimation(0).getDirection(0).getSprite(0).getImageName()
|
||||
animations.getAnimation(0).getDirection(0).getSprite(0).getImageName()
|
||||
).toBe('image2');
|
||||
});
|
||||
|
||||
|
@@ -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,51 @@ 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);
|
||||
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",
|
||||
"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);
|
||||
|
595
GDevelop.js/types.d.ts
vendored
595
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;
|
||||
|
@@ -6,6 +6,7 @@ declare class gdCustomObjectConfiguration extends gdObjectConfiguration {
|
||||
updateProperty(name: string, value: string): boolean;
|
||||
getInitialInstanceProperties(instance: gdInitialInstance, project: gdProject, scene: gdLayout): gdMapStringPropertyDescriptor;
|
||||
updateInitialInstanceProperty(instance: gdInitialInstance, name: string, value: string, project: gdProject, scene: gdLayout): boolean;
|
||||
getAnimations(): gdSpriteAnimationList;
|
||||
delete(): void;
|
||||
ptr: number;
|
||||
};
|
@@ -11,6 +11,10 @@ declare class gdEventsBasedObject extends gdAbstractEventsBasedEntity {
|
||||
getDefaultName(): string;
|
||||
markAsRenderedIn3D(isRenderedIn3D: boolean): gdEventsBasedObject;
|
||||
isRenderedIn3D(): boolean;
|
||||
markAsAnimatable(isAnimatable: boolean): gdEventsBasedObject;
|
||||
isAnimatable(): boolean;
|
||||
markAsTextContainer(isTextContainer: boolean): gdEventsBasedObject;
|
||||
isTextContainer(): boolean;
|
||||
static getPropertyActionName(propertyName: string): string;
|
||||
static getPropertyConditionName(propertyName: string): string;
|
||||
static getPropertyExpressionName(propertyName: string): string;
|
||||
|
@@ -19,6 +19,8 @@ declare class gdInitialInstance {
|
||||
setLocked(lock: boolean): void;
|
||||
isSealed(): boolean;
|
||||
setSealed(seal: boolean): void;
|
||||
shouldKeepRatio(): boolean;
|
||||
setShouldKeepRatio(keepRatio: boolean): void;
|
||||
getZOrder(): number;
|
||||
setZOrder(zOrder: number): void;
|
||||
getLayer(): string;
|
||||
|
16
GDevelop.js/types/gdspriteanimationlist.js
Normal file
16
GDevelop.js/types/gdspriteanimationlist.js
Normal file
@@ -0,0 +1,16 @@
|
||||
// Automatically generated by GDevelop.js/scripts/generate-types.js
|
||||
declare class gdSpriteAnimationList {
|
||||
constructor(): void;
|
||||
addAnimation(animation: gdAnimation): void;
|
||||
getAnimation(index: number): gdAnimation;
|
||||
getAnimationsCount(): number;
|
||||
removeAnimation(index: number): void;
|
||||
removeAllAnimations(): void;
|
||||
hasNoAnimations(): boolean;
|
||||
swapAnimations(first: number, second: number): void;
|
||||
moveAnimation(oldIndex: number, newIndex: number): void;
|
||||
adaptCollisionMaskAutomatically(): boolean;
|
||||
setAdaptCollisionMaskAutomatically(adaptCollisionMaskAutomatically: boolean): void;
|
||||
delete(): void;
|
||||
ptr: number;
|
||||
};
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user