mirror of
https://github.com/4ian/GDevelop.git
synced 2025-10-15 10:19:04 +00:00
Compare commits
129 Commits
v5.4.204
...
experiment
Author | SHA1 | Date | |
---|---|---|---|
![]() |
5eb5fb3af9 | ||
![]() |
cd80872fca | ||
![]() |
61cb6dde0e | ||
![]() |
29c8de0987 | ||
![]() |
802e9a5128 | ||
![]() |
c82602919b | ||
![]() |
80cbb8f542 | ||
![]() |
a9ceba7bef | ||
![]() |
7d9e72c876 | ||
![]() |
3baf5903d3 | ||
![]() |
6008e1045d | ||
![]() |
9dda9a89c5 | ||
![]() |
814c6aec4f | ||
![]() |
84e4158407 | ||
![]() |
aa6c3bc1c8 | ||
![]() |
41dc6d0966 | ||
![]() |
9c19865dec | ||
![]() |
bbfb7f63f0 | ||
![]() |
2f8304c2dd | ||
![]() |
c1aa88861d | ||
![]() |
254ab0350b | ||
![]() |
b0a3c34803 | ||
![]() |
63a3265310 | ||
![]() |
d19292f43d | ||
![]() |
3646d05b65 | ||
![]() |
25a4d04896 | ||
![]() |
2df6c13ed7 | ||
![]() |
93f84a14cb | ||
![]() |
02e0ebf63b | ||
![]() |
da3abb331a | ||
![]() |
a5a9524ed6 | ||
![]() |
c9cc1f6fdc | ||
![]() |
de140f1190 | ||
![]() |
9a82fda7fe | ||
![]() |
eac92704fa | ||
![]() |
dc607d85c3 | ||
![]() |
e96269d899 | ||
![]() |
05d622c5c0 | ||
![]() |
0758397196 | ||
![]() |
65293ddd99 | ||
![]() |
225a3a67c6 | ||
![]() |
a96171aacd | ||
![]() |
1a21a0bfb3 | ||
![]() |
cc23301875 | ||
![]() |
aa513c04e6 | ||
![]() |
a4e8e8c00b | ||
![]() |
0d34680fcd | ||
![]() |
4abdb9dca6 | ||
![]() |
db05a07023 | ||
![]() |
78ebe58713 | ||
![]() |
420c7a4429 | ||
![]() |
1442a2772e | ||
![]() |
ce18bdd5a7 | ||
![]() |
2f2cc1bbe3 | ||
![]() |
097ad4fff5 | ||
![]() |
2112ed789a | ||
![]() |
a41a1c14a0 | ||
![]() |
771d3264bb | ||
![]() |
9fa1e552e0 | ||
![]() |
503a0873d9 | ||
![]() |
715480bdef | ||
![]() |
869fd7eb08 | ||
![]() |
e0cb8e4953 | ||
![]() |
0ef4953241 | ||
![]() |
d154384164 | ||
![]() |
504df2e0a3 | ||
![]() |
e9adaa94c5 | ||
![]() |
35da31c5c5 | ||
![]() |
e65492e1a1 | ||
![]() |
44827ea372 | ||
![]() |
ab3ffe6785 | ||
![]() |
d83d049ac9 | ||
![]() |
67a7bd7af2 | ||
![]() |
6db5267878 | ||
![]() |
a51c223c9c | ||
![]() |
0a4e5a1012 | ||
![]() |
acce714736 | ||
![]() |
3c34a8806b | ||
![]() |
1d4cb7bef0 | ||
![]() |
7badacd24a | ||
![]() |
11ab92fc0e | ||
![]() |
ddb1e335bc | ||
![]() |
8d035a774d | ||
![]() |
5b1e3565d3 | ||
![]() |
8c88038bfb | ||
![]() |
f62811974d | ||
![]() |
b516037d2b | ||
![]() |
98befc8000 | ||
![]() |
377231fb37 | ||
![]() |
22ae8ac489 | ||
![]() |
40674fd3b9 | ||
![]() |
0792e59b24 | ||
![]() |
8ba6ad7b43 | ||
![]() |
84b07bc84d | ||
![]() |
c46d39cbed | ||
![]() |
b96132964c | ||
![]() |
130cd1e3a7 | ||
![]() |
fbbcf25bf5 | ||
![]() |
ffaae4d3d4 | ||
![]() |
75d79a7758 | ||
![]() |
d91fb78848 | ||
![]() |
e0a2ed1654 | ||
![]() |
d5f2be1c19 | ||
![]() |
7abcfe8af2 | ||
![]() |
b86dd9efce | ||
![]() |
15f6b62c5b | ||
![]() |
eb995ec7c7 | ||
![]() |
a076571120 | ||
![]() |
ec9cb790e7 | ||
![]() |
4a283add00 | ||
![]() |
6b3faa42bb | ||
![]() |
555ee61e63 | ||
![]() |
b838c8549b | ||
![]() |
33db6ee359 | ||
![]() |
f361d3e1fa | ||
![]() |
441401f34c | ||
![]() |
558daa2075 | ||
![]() |
cd475316df | ||
![]() |
8b21e72c85 | ||
![]() |
a9d6f18c11 | ||
![]() |
f58e1113b6 | ||
![]() |
f82b5fc66d | ||
![]() |
2f19a9bb33 | ||
![]() |
8f739d85c2 | ||
![]() |
f23847617d | ||
![]() |
876332a782 | ||
![]() |
93c74c9fd6 | ||
![]() |
e92d8496ac | ||
![]() |
35e67a6d26 |
3
.gitattributes
vendored
3
.gitattributes
vendored
@@ -1,12 +1,11 @@
|
||||
Core/GDCore/Serialization/rapidjson/rapidjson.h/* linguist-vendored
|
||||
Core/GDCore/TinyXml/* linguist-vendored
|
||||
Extensions/ParticleSystem/SPARK/* linguist-vendored
|
||||
Extensions/PhysicsBehavior/Box2D/* linguist-vendored
|
||||
Extensions/PhysicsBehavior/box2djs/* linguist-vendored
|
||||
Extensions/Physics2Behavior/box2d.js linguist-vendored
|
||||
Extensions/BBText/pixi-multistyle-text/* linguist-vendored
|
||||
Extensions/P2P/A_peer.js linguist-vendored
|
||||
Extensions/Multiplayer/peer.js linguist-vendored
|
||||
Extensions/Shopify/shopify-buy.umd.polyfilled.min.js linguist-vendored
|
||||
Extensions/TileMap/pako/* linguist-vendored
|
||||
Extensions/TileMap/pixi-tilemap/* linguist-vendored
|
||||
Extensions/TweenBehavior/shifty.js linguist-vendored
|
||||
|
35
.travis.yml
35
.travis.yml
@@ -17,11 +17,11 @@ cache:
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
# Build dependencies:
|
||||
- cmake
|
||||
- p7zip-full
|
||||
# Build dependencies:
|
||||
- cmake
|
||||
- p7zip-full
|
||||
|
||||
before_install:
|
||||
# This workaround is required to avoid libstdc++ errors (Emscripten requires a recent version of libstdc++)
|
||||
@@ -29,47 +29,48 @@ before_install:
|
||||
- sudo dpkg --force-all -i libstdc++6
|
||||
|
||||
install:
|
||||
# Ensure we use a recent version of Node.js (and npm).
|
||||
# Ensure we use a recent version of Node.js (and npm).
|
||||
- nvm install v16 && nvm use v16
|
||||
#Compile the tests only for GDCore
|
||||
#Compile the tests only for GDCore
|
||||
- mkdir .build-tests
|
||||
- cd .build-tests
|
||||
- cmake -DBUILD_GDJS=FALSE -DBUILD_TESTS=TRUE -DCMAKE_CXX_COMPILER=$(which $CXX) -DCMAKE_C_COMPILER=$(which $CC) ..
|
||||
- make -j 4
|
||||
- cd ..
|
||||
# Install Emscripten (for GDevelop.js)
|
||||
- git clone https://github.com/juj/emsdk.git
|
||||
# Install Emscripten (for GDevelop.js)
|
||||
# Specify the tag for the core repository to avois breaking changes.
|
||||
- git clone --depth 1 --branch 3.1.21 https://github.com/juj/emsdk.git
|
||||
- cd emsdk && ./emsdk install 3.1.21 && ./emsdk activate 3.1.21 && cd ..
|
||||
# Install GDevelop.js dependencies
|
||||
# Install GDevelop.js dependencies
|
||||
- cd GDevelop.js && npm install && cd ..
|
||||
# Build GDevelop.js
|
||||
# (in a subshell to avoid Emscripten polluting the Node.js and npm version for the rest of the build)
|
||||
# Build GDevelop.js
|
||||
# (in a subshell to avoid Emscripten polluting the Node.js and npm version for the rest of the build)
|
||||
- (set -e; cd GDevelop.js && source ../emsdk/emsdk_env.sh && npm run build && cd ..)
|
||||
# Install newIDE tests dependencies
|
||||
# Install newIDE tests dependencies
|
||||
- npm -v
|
||||
- cd newIDE/app && npm install
|
||||
- cd ../..
|
||||
# Install GDJS tests dependencies
|
||||
# Install GDJS tests dependencies
|
||||
- cd GDJS && npm install && cd tests && npm install
|
||||
- cd ../..
|
||||
|
||||
script:
|
||||
# GDCore tests:
|
||||
# GDCore tests:
|
||||
- cd .build-tests
|
||||
- Core/GDCore_tests
|
||||
- cd ..
|
||||
# GDevelop.js tests
|
||||
# GDevelop.js tests
|
||||
- cd GDevelop.js
|
||||
- npm test
|
||||
- cd ..
|
||||
# newIDE tests:
|
||||
# newIDE tests:
|
||||
- cd newIDE/app
|
||||
- npm test
|
||||
- npm run flow
|
||||
- npm run check-format
|
||||
- npm run check-script-types
|
||||
- cd ../..
|
||||
# GDJS tests:
|
||||
# GDJS tests:
|
||||
- cd GDJS
|
||||
- npm run check-format
|
||||
- cd ..
|
||||
|
@@ -58,99 +58,7 @@
|
||||
* Common functions and tools for programming.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \defgroup TinyXml Integrated TinyXml library
|
||||
*
|
||||
* See the full documentation of TinyXml [here](http://www.grinninglizard.com/tinyxmldocs/index.html).
|
||||
*/
|
||||
|
||||
/**
|
||||
* \defgroup SpriteObjectExtension Standard Sprite Object extension
|
||||
* \ingroup BuiltinExtensions
|
||||
*/
|
||||
|
||||
/**
|
||||
* \class TiXmlAttribute
|
||||
* \brief Part of the tinyxml library
|
||||
* \ingroup TinyXml
|
||||
*/
|
||||
/**
|
||||
* \class TiXmlAttributeSet
|
||||
* \brief Part of the tinyxml library
|
||||
* \ingroup TinyXml
|
||||
*/
|
||||
/**
|
||||
* \class TiXmlBase
|
||||
* \brief Part of the tinyxml library
|
||||
* \ingroup TinyXml
|
||||
*/
|
||||
/**
|
||||
* \class TiXmlComment
|
||||
* \brief Part of the tinyxml library
|
||||
* \ingroup TinyXml
|
||||
*/
|
||||
/**
|
||||
* \class TiXmlCursor
|
||||
* \brief Part of the tinyxml library
|
||||
* \ingroup TinyXml
|
||||
*/
|
||||
/**
|
||||
* \class TiXmlDeclaration
|
||||
* \brief Part of the tinyxml library
|
||||
* \ingroup TinyXml
|
||||
*/
|
||||
/**
|
||||
* \class TiXmlDocument
|
||||
* \brief Part of the tinyxml library
|
||||
* \ingroup TinyXml
|
||||
*/
|
||||
/**
|
||||
* \class TiXmlElement
|
||||
* \brief Part of the tinyxml library
|
||||
* \ingroup TinyXml
|
||||
*/
|
||||
/**
|
||||
* \class TiXmlHandle
|
||||
* \brief Part of the tinyxml library
|
||||
* \ingroup TinyXml
|
||||
*/
|
||||
/**
|
||||
* \class TiXmlNode
|
||||
* \brief Part of the tinyxml library
|
||||
* \ingroup TinyXml
|
||||
*/
|
||||
/**
|
||||
* \class TiXmlOutStream
|
||||
* \brief Part of the tinyxml library
|
||||
* \ingroup TinyXml
|
||||
*/
|
||||
/**
|
||||
* \class TiXmlParsingData
|
||||
* \brief Part of the tinyxml library
|
||||
* \ingroup TinyXml
|
||||
*/
|
||||
/**
|
||||
* \class TiXmlPrinter
|
||||
* \brief Part of the tinyxml library
|
||||
* \ingroup TinyXml
|
||||
*/
|
||||
/**
|
||||
* \class TiXmlString
|
||||
* \brief Part of the tinyxml library
|
||||
* \ingroup TinyXml
|
||||
*/
|
||||
/**
|
||||
* \class TiXmlText
|
||||
* \brief Part of the tinyxml library
|
||||
* \ingroup TinyXml
|
||||
*/
|
||||
/**
|
||||
* \class TiXmlUnknown
|
||||
* \brief Part of the tinyxml library
|
||||
* \ingroup TinyXml
|
||||
*/
|
||||
/**
|
||||
* \class TiXmlVisitor
|
||||
* \brief Part of the tinyxml library
|
||||
* \ingroup TinyXml
|
||||
*/
|
||||
*/
|
@@ -8,7 +8,6 @@
|
||||
#include "GDCore/Events/Serialization.h"
|
||||
#include "GDCore/Events/Tools/EventsCodeNameMangler.h"
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
#include "GDCore/TinyXml/tinyxml.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
@@ -10,7 +10,6 @@
|
||||
#include "GDCore/Events/CodeGeneration/EventsCodeGenerator.h"
|
||||
#include "GDCore/Events/Serialization.h"
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
#include "GDCore/TinyXml/tinyxml.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
@@ -15,6 +15,7 @@
|
||||
#include "GDCore/Project/Layout.h"
|
||||
#include "GDCore/Project/Object.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/Project/EventsFunctionsExtension.h"
|
||||
#include "GDCore/IDE/ProjectBrowserHelper.h"
|
||||
|
||||
namespace gd {
|
||||
@@ -47,6 +48,9 @@ void EffectsCodeGenerator::GenerateEffectsIncludeFiles(
|
||||
|
||||
// TODO Merge with UsedExtensionsFinder.
|
||||
|
||||
// TODO Factorize with the iteration on all effects for resource exposure.
|
||||
// TODO Implement an ArbitraryEffectWorker and add a method in ProjectBrowserHelper
|
||||
|
||||
// See also gd::Project::ExposeResources for a method that traverse the whole
|
||||
// project (this time for resources) and
|
||||
// WholeProjectRefactorer::ExposeProjectEvents.
|
||||
@@ -68,6 +72,27 @@ void EffectsCodeGenerator::GenerateEffectsIncludeFiles(
|
||||
|
||||
// Add objects effects
|
||||
gd::ProjectBrowserHelper::ExposeProjectObjects(project, effectsCodeGenerator);
|
||||
|
||||
// Add event-based objects layouts effects
|
||||
for (std::size_t s = 0; s < project.GetEventsFunctionsExtensionsCount();
|
||||
s++) {
|
||||
auto &eventsFunctionExtension = project.GetEventsFunctionsExtension(s);
|
||||
|
||||
auto &eventsBasedObjects = eventsFunctionExtension.GetEventsBasedObjects();
|
||||
for (std::size_t objectIndex = 0;
|
||||
objectIndex < eventsBasedObjects.GetCount(); ++objectIndex) {
|
||||
auto &eventsBasedObject = eventsBasedObjects.Get(objectIndex);
|
||||
|
||||
auto &layers = eventsBasedObject.GetLayers();
|
||||
for (std::size_t l = 0; l < layers.GetLayersCount(); ++l) {
|
||||
auto &effects = layers.GetLayer(l).GetEffects();
|
||||
for (std::size_t e = 0; e < effects.GetEffectsCount(); ++e) {
|
||||
auto &effect = effects.GetEffect(e);
|
||||
effectsCodeGenerator.AddEffectIncludeFiles(effect);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -709,11 +709,14 @@ EventsCodeGenerator::GenerateCallback(
|
||||
const gd::String actionsDeclarationsCode =
|
||||
GenerateObjectsDeclarationCode(callbackContext);
|
||||
|
||||
const gd::String callbackCode =
|
||||
callbackFunctionName + " = function (" +
|
||||
GenerateEventsParameters(callbackContext) + ") {\n" +
|
||||
restoreLocalVariablesCode +
|
||||
actionsDeclarationsCode + actionsCode + "}\n";
|
||||
const gd::String clearLocalVariablesCode =
|
||||
GenerateLocalVariablesStackAccessor() + ".length = 0;\n";
|
||||
|
||||
const gd::String callbackCode = callbackFunctionName + " = function (" +
|
||||
GenerateEventsParameters(callbackContext) +
|
||||
") {\n" + restoreLocalVariablesCode +
|
||||
actionsDeclarationsCode + actionsCode +
|
||||
clearLocalVariablesCode + "}\n";
|
||||
|
||||
AddCustomCodeOutsideMain(callbackCode);
|
||||
|
||||
|
@@ -18,7 +18,6 @@ class BaseEvent;
|
||||
namespace gd {
|
||||
class SerializerElement;
|
||||
}
|
||||
class TiXmlElement;
|
||||
|
||||
#undef CreateEvent
|
||||
|
||||
|
@@ -58,6 +58,7 @@ struct GD_CORE_API ExpressionParserError {
|
||||
MalformedObjectParameter,
|
||||
UnknownParameterType,
|
||||
MissingBehavior,
|
||||
VariableNameCollision,
|
||||
};
|
||||
|
||||
ExpressionParserError(gd::ExpressionParserError::ErrorType type_,
|
||||
|
@@ -1377,7 +1377,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
_("Variables"),
|
||||
"res/actions/var.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("objectvar", _("Variable"));
|
||||
.AddParameter("objectvar", _("Variable"))
|
||||
.SetRelevantForFunctionEventsOnly();
|
||||
|
||||
obj.AddExpression("ObjectTimerElapsedTime",
|
||||
_("Object timer value"),
|
||||
|
@@ -327,6 +327,25 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
|
||||
.AddParameter("expression", _("Camera number (default : 0)"), "", true)
|
||||
.SetDefaultValue("0");
|
||||
|
||||
extension
|
||||
.AddCondition(
|
||||
"CameraZoom",
|
||||
_("Camera zoom"),
|
||||
_("Compare the zoom of a camera of a layer."),
|
||||
_("Zoom of camera _PARAM2_ of layer _PARAM1_"),
|
||||
"",
|
||||
"res/conditions/camera24.png",
|
||||
"res/conditions/camera.png")
|
||||
.AddCodeOnlyParameter("currentScene", "")
|
||||
.AddParameter("layer", _("Layer"), "", true)
|
||||
.SetDefaultValue("\"\"")
|
||||
.AddParameter("expression", _("Camera number (default : 0)"), "", true)
|
||||
.SetDefaultValue("0")
|
||||
.UseStandardRelationalOperatorParameters(
|
||||
"number", gd::ParameterOptions::MakeNewOptions().SetDescription(
|
||||
_("Zoom")))
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
.AddAction(
|
||||
"FixCamera",
|
||||
|
@@ -64,9 +64,7 @@ void SpriteObject::ExposeResources(gd::ArbitraryResourceWorker& worker) {
|
||||
|
||||
std::map<gd::String, gd::PropertyDescriptor>
|
||||
SpriteObject::GetInitialInstanceProperties(
|
||||
const gd::InitialInstance& initialInstance,
|
||||
gd::Project& project,
|
||||
gd::Layout& scene) {
|
||||
const gd::InitialInstance& initialInstance) {
|
||||
std::map<gd::String, gd::PropertyDescriptor> properties;
|
||||
properties["animation"] =
|
||||
gd::PropertyDescriptor(
|
||||
@@ -80,9 +78,7 @@ SpriteObject::GetInitialInstanceProperties(
|
||||
bool SpriteObject::UpdateInitialInstanceProperty(
|
||||
gd::InitialInstance& initialInstance,
|
||||
const gd::String& name,
|
||||
const gd::String& value,
|
||||
gd::Project& project,
|
||||
gd::Layout& scene) {
|
||||
const gd::String& value) {
|
||||
if (name == "animation") {
|
||||
initialInstance.SetRawDoubleProperty(
|
||||
"animation", std::max(0, value.empty() ? 0 : value.To<int>()));
|
||||
|
@@ -47,14 +47,10 @@ class GD_CORE_API SpriteObject : public gd::ObjectConfiguration {
|
||||
bool UpdateProperty(const gd::String& name, const gd::String& value) override;
|
||||
|
||||
std::map<gd::String, gd::PropertyDescriptor> GetInitialInstanceProperties(
|
||||
const gd::InitialInstance& position,
|
||||
gd::Project& project,
|
||||
gd::Layout& scene) override;
|
||||
const gd::InitialInstance& position) override;
|
||||
bool UpdateInitialInstanceProperty(gd::InitialInstance& position,
|
||||
const gd::String& name,
|
||||
const gd::String& value,
|
||||
gd::Project& project,
|
||||
gd::Layout& scene) override;
|
||||
const gd::String& value) override;
|
||||
|
||||
/**
|
||||
* \brief Return the animation configuration.
|
||||
|
@@ -231,8 +231,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
"it is a text (string)."),
|
||||
_("Arrays and structures"),
|
||||
"res/actions/var.png")
|
||||
.AddParameter("variable", _("Array variable"))
|
||||
.SetRelevantForLayoutEventsOnly();
|
||||
.AddParameter("variable", _("Array variable"));
|
||||
|
||||
extension
|
||||
.AddExpression(
|
||||
@@ -242,8 +241,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
"it is a number."),
|
||||
_("Arrays and structures"),
|
||||
"res/actions/var.png")
|
||||
.AddParameter("variable", _("Array variable"))
|
||||
.SetRelevantForLayoutEventsOnly();
|
||||
.AddParameter("variable", _("Array variable"));
|
||||
|
||||
extension
|
||||
.AddStrExpression(
|
||||
@@ -253,8 +251,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
"it is a text (string)."),
|
||||
_("Arrays and structures"),
|
||||
"res/actions/var.png")
|
||||
.AddParameter("variable", _("Array variable"))
|
||||
.SetRelevantForLayoutEventsOnly();
|
||||
.AddParameter("variable", _("Array variable"));
|
||||
|
||||
extension
|
||||
.AddExpression(
|
||||
@@ -264,8 +261,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
"it is a number."),
|
||||
_("Arrays and structures"),
|
||||
"res/actions/var.png")
|
||||
.AddParameter("variable", _("Array variable"))
|
||||
.SetRelevantForLayoutEventsOnly();
|
||||
.AddParameter("variable", _("Array variable"));
|
||||
|
||||
// Legacy instructions
|
||||
|
||||
@@ -839,7 +835,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
_("Number of children"),
|
||||
_("Number of children in a scene array or "
|
||||
"structure variable"),
|
||||
_("External variables/Scene variables/Arrays and structures"),
|
||||
_("Arrays and structures"),
|
||||
"res/actions/var.png")
|
||||
.AddParameter("variable", _("Array or structure variable"), "AllowUndeclaredVariable");
|
||||
|
||||
|
@@ -96,11 +96,11 @@ std::shared_ptr<gd::PlatformExtension> Platform::GetExtension(
|
||||
std::unique_ptr<gd::ObjectConfiguration> Platform::CreateObjectConfiguration(
|
||||
gd::String type) const {
|
||||
if (creationFunctionTable.find(type) == creationFunctionTable.end()) {
|
||||
gd::LogWarning("Tried to create an object with an unknown type: " + type
|
||||
gd::LogWarning("Tried to create an object configuration with an unknown type: " + type
|
||||
+ " for platform " + GetName() + "!");
|
||||
type = "";
|
||||
if (creationFunctionTable.find("") == creationFunctionTable.end()) {
|
||||
gd::LogError("Unable to create a Base object!");
|
||||
gd::LogFatalError("Unable to create a base object configuration!");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
@@ -296,7 +296,7 @@ class GD_CORE_API ExpressionObjectFinder : public ExpressionParser2NodeWorker {
|
||||
};
|
||||
|
||||
bool EventsRefactorer::RenameObjectInActions(const gd::Platform& platform,
|
||||
gd::ProjectScopedContainers& projectScopedContainers,
|
||||
const gd::ProjectScopedContainers& projectScopedContainers,
|
||||
gd::InstructionsList& actions,
|
||||
gd::String oldName,
|
||||
gd::String newName) {
|
||||
@@ -347,7 +347,7 @@ bool EventsRefactorer::RenameObjectInActions(const gd::Platform& platform,
|
||||
|
||||
bool EventsRefactorer::RenameObjectInConditions(
|
||||
const gd::Platform& platform,
|
||||
gd::ProjectScopedContainers& projectScopedContainers,
|
||||
const gd::ProjectScopedContainers& projectScopedContainers,
|
||||
gd::InstructionsList& conditions,
|
||||
gd::String oldName,
|
||||
gd::String newName) {
|
||||
@@ -399,7 +399,7 @@ bool EventsRefactorer::RenameObjectInConditions(
|
||||
|
||||
bool EventsRefactorer::RenameObjectInEventParameters(
|
||||
const gd::Platform& platform,
|
||||
gd::ProjectScopedContainers& projectScopedContainers,
|
||||
const gd::ProjectScopedContainers& projectScopedContainers,
|
||||
gd::Expression& expression,
|
||||
gd::ParameterMetadata parameterMetadata,
|
||||
gd::String oldName,
|
||||
@@ -432,7 +432,7 @@ bool EventsRefactorer::RenameObjectInEventParameters(
|
||||
}
|
||||
|
||||
void EventsRefactorer::RenameObjectInEvents(const gd::Platform& platform,
|
||||
gd::ProjectScopedContainers& projectScopedContainers,
|
||||
const gd::ProjectScopedContainers& projectScopedContainers,
|
||||
gd::EventsList& events,
|
||||
gd::String oldName,
|
||||
gd::String newName) {
|
||||
@@ -475,7 +475,7 @@ void EventsRefactorer::RenameObjectInEvents(const gd::Platform& platform,
|
||||
}
|
||||
|
||||
bool EventsRefactorer::RemoveObjectInActions(const gd::Platform& platform,
|
||||
gd::ProjectScopedContainers& projectScopedContainers,
|
||||
const gd::ProjectScopedContainers& projectScopedContainers,
|
||||
gd::InstructionsList& actions,
|
||||
gd::String name) {
|
||||
bool somethingModified = false;
|
||||
@@ -532,7 +532,7 @@ bool EventsRefactorer::RemoveObjectInActions(const gd::Platform& platform,
|
||||
|
||||
bool EventsRefactorer::RemoveObjectInConditions(
|
||||
const gd::Platform& platform,
|
||||
gd::ProjectScopedContainers& projectScopedContainers,
|
||||
const gd::ProjectScopedContainers& projectScopedContainers,
|
||||
gd::InstructionsList& conditions,
|
||||
gd::String name) {
|
||||
bool somethingModified = false;
|
||||
|
@@ -3,8 +3,8 @@
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#ifndef GDCORE_EVENTSREFACTORER_H
|
||||
#define GDCORE_EVENTSREFACTORER_H
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
@@ -81,7 +81,7 @@ class GD_CORE_API EventsRefactorer {
|
||||
* events ).
|
||||
*/
|
||||
static void RenameObjectInEvents(const gd::Platform& platform,
|
||||
gd::ProjectScopedContainers& projectScopedContainers,
|
||||
const gd::ProjectScopedContainers& projectScopedContainers,
|
||||
gd::EventsList& events,
|
||||
gd::String oldName,
|
||||
gd::String newName);
|
||||
@@ -128,7 +128,7 @@ class GD_CORE_API EventsRefactorer {
|
||||
* \return true if something was modified.
|
||||
*/
|
||||
static bool RenameObjectInActions(const gd::Platform& platform,
|
||||
gd::ProjectScopedContainers& projectScopedContainers,
|
||||
const gd::ProjectScopedContainers& projectScopedContainers,
|
||||
gd::InstructionsList& instructions,
|
||||
gd::String oldName,
|
||||
gd::String newName);
|
||||
@@ -140,7 +140,7 @@ class GD_CORE_API EventsRefactorer {
|
||||
* \return true if something was modified.
|
||||
*/
|
||||
static bool RenameObjectInConditions(const gd::Platform& platform,
|
||||
gd::ProjectScopedContainers& projectScopedContainers,
|
||||
const gd::ProjectScopedContainers& projectScopedContainers,
|
||||
gd::InstructionsList& instructions,
|
||||
gd::String oldName,
|
||||
gd::String newName);
|
||||
@@ -153,7 +153,7 @@ class GD_CORE_API EventsRefactorer {
|
||||
*/
|
||||
static bool RenameObjectInEventParameters(
|
||||
const gd::Platform& platform,
|
||||
gd::ProjectScopedContainers& projectScopedContainers,
|
||||
const gd::ProjectScopedContainers& projectScopedContainers,
|
||||
gd::Expression& expression,
|
||||
gd::ParameterMetadata parameterMetadata,
|
||||
gd::String oldName,
|
||||
@@ -165,7 +165,7 @@ class GD_CORE_API EventsRefactorer {
|
||||
* \return true if something was modified.
|
||||
*/
|
||||
static bool RemoveObjectInConditions(const gd::Platform& platform,
|
||||
gd::ProjectScopedContainers& projectScopedContainers,
|
||||
const gd::ProjectScopedContainers& projectScopedContainers,
|
||||
gd::InstructionsList& conditions,
|
||||
gd::String name);
|
||||
|
||||
@@ -175,7 +175,7 @@ class GD_CORE_API EventsRefactorer {
|
||||
* \return true if something was modified.
|
||||
*/
|
||||
static bool RemoveObjectInActions(const gd::Platform& platform,
|
||||
gd::ProjectScopedContainers& projectScopedContainers,
|
||||
const gd::ProjectScopedContainers& projectScopedContainers,
|
||||
gd::InstructionsList& conditions,
|
||||
gd::String name);
|
||||
|
||||
@@ -242,5 +242,3 @@ class GD_CORE_API EventsRefactorer {
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
||||
#endif // GDCORE_EVENTSREFACTORER_H
|
||||
|
@@ -203,13 +203,7 @@ class GD_CORE_API ExpressionValidator : public ExpressionParser2NodeWorker {
|
||||
if (parentType == Type::Variable) {
|
||||
childType = parentType;
|
||||
|
||||
if (!currentParameterExtraInfo || *currentParameterExtraInfo != "AllowUndeclaredVariable") {
|
||||
const auto& variablesContainersList = projectScopedContainers.GetVariablesContainersList();
|
||||
if (!variablesContainersList.Has(node.name)) {
|
||||
RaiseUndeclaredVariableError(_("No variable with this name found."), node.location, node.name);
|
||||
}
|
||||
}
|
||||
|
||||
CheckVariableExistence(node.location, node.name);
|
||||
if (node.child) {
|
||||
node.child->Visit(*this);
|
||||
}
|
||||
@@ -333,12 +327,7 @@ class GD_CORE_API ExpressionValidator : public ExpressionParser2NodeWorker {
|
||||
}
|
||||
}
|
||||
else if (parentType == Type::Variable) {
|
||||
if (!currentParameterExtraInfo || *currentParameterExtraInfo != "AllowUndeclaredVariable") {
|
||||
const auto& variablesContainersList = projectScopedContainers.GetVariablesContainersList();
|
||||
if (!variablesContainersList.Has(node.identifierName)) {
|
||||
RaiseUndeclaredVariableError(_("No variable with this name found."), node.location, node.identifierName);
|
||||
}
|
||||
}
|
||||
CheckVariableExistence(node.location, node.identifierName);
|
||||
}
|
||||
else if (parentType != Type::Object && parentType != Type::LegacyVariable) {
|
||||
// It can't happen.
|
||||
@@ -381,6 +370,45 @@ class GD_CORE_API ExpressionValidator : public ExpressionParser2NodeWorker {
|
||||
Type ValidateFunction(const gd::FunctionCallNode& function);
|
||||
bool ValidateObjectVariableOrVariableOrProperty(const gd::IdentifierNode& identifier);
|
||||
|
||||
void CheckVariableExistence(const ExpressionParserLocation &location, const gd::String& name) {
|
||||
if (!currentParameterExtraInfo || *currentParameterExtraInfo != "AllowUndeclaredVariable") {
|
||||
projectScopedContainers.MatchIdentifierWithName<void>(
|
||||
name,
|
||||
[&]() {
|
||||
// This represents an object.
|
||||
RaiseVariableNameCollisionError(
|
||||
_("This variable has the same name as an object. Consider "
|
||||
"renaming one or the other."),
|
||||
location, name);
|
||||
},
|
||||
[&]() {
|
||||
// This is a variable.
|
||||
},
|
||||
[&]() {
|
||||
// This is a property.
|
||||
// This error won't happen unless the priority is changed.
|
||||
RaiseVariableNameCollisionError(
|
||||
_("This variable has the same name as a property. Consider "
|
||||
"renaming one or the other."),
|
||||
location, name);
|
||||
},
|
||||
[&]() {
|
||||
// This is a parameter.
|
||||
// This error won't happen unless the priority is changed.
|
||||
RaiseVariableNameCollisionError(
|
||||
_("This variable has the same name as a parameter. Consider "
|
||||
"renaming one or the other."),
|
||||
location, name);
|
||||
},
|
||||
[&]() {
|
||||
// This is something else.
|
||||
RaiseUndeclaredVariableError(
|
||||
_("No variable with this name found."), location,
|
||||
name);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void ReportAnyError(const ExpressionNode& node, bool isFatal = true) {
|
||||
if (node.diagnostic) {
|
||||
// Syntax errors are holden by the AST nodes.
|
||||
@@ -424,6 +452,14 @@ class GD_CORE_API ExpressionValidator : public ExpressionParser2NodeWorker {
|
||||
message, location, true, variableName, objectName);
|
||||
}
|
||||
|
||||
void RaiseVariableNameCollisionError(const gd::String &message,
|
||||
const ExpressionParserLocation &location,
|
||||
const gd::String &variableName,
|
||||
const gd::String &objectName = "") {
|
||||
RaiseError(gd::ExpressionParserError::ErrorType::VariableNameCollision,
|
||||
message, location, false, variableName, objectName);
|
||||
}
|
||||
|
||||
void RaiseTypeError(const gd::String &message,
|
||||
const ExpressionParserLocation &location,
|
||||
bool isFatal = true) {
|
||||
|
@@ -20,7 +20,7 @@ namespace gd {
|
||||
|
||||
void EventsFunctionTools::FreeEventsFunctionToObjectsContainer(
|
||||
const gd::Project& project,
|
||||
const gd::EventsFunctionsContainer functionContainer,
|
||||
const gd::EventsFunctionsContainer& functionContainer,
|
||||
const gd::EventsFunction& eventsFunction,
|
||||
gd::ObjectsContainer& outputObjectsContainer) {
|
||||
// Functions scope for objects is defined according
|
||||
@@ -92,17 +92,30 @@ void EventsFunctionTools::ObjectEventsFunctionToObjectsContainer(
|
||||
"its parameters).");
|
||||
return;
|
||||
}
|
||||
if (eventsBasedObject.HasObjectNamed("Object")) {
|
||||
if (eventsBasedObject.GetObjects().HasObjectNamed("Object")) {
|
||||
gd::LogWarning("Child-objects can't be named Object because it's reserved"
|
||||
"for the parent. ");
|
||||
return;
|
||||
}
|
||||
|
||||
// ...and its children.
|
||||
auto &children = eventsBasedObject.GetObjects();
|
||||
gd::EventsFunctionTools::CopyEventsBasedObjectChildrenToObjectsContainer(
|
||||
eventsBasedObject, outputObjectsContainer);
|
||||
}
|
||||
|
||||
void EventsFunctionTools::CopyEventsBasedObjectChildrenToObjectsContainer(
|
||||
const gd::EventsBasedObject& eventsBasedObject,
|
||||
gd::ObjectsContainer& outputObjectsContainer) {
|
||||
auto &children = eventsBasedObject.GetObjects().GetObjects();
|
||||
for (auto &childObject : children) {
|
||||
auto child = childObject.get();
|
||||
outputObjectsContainer.InsertObject(*child, children.size());
|
||||
outputObjectsContainer.InsertObject(
|
||||
*child, outputObjectsContainer.GetObjectsCount());
|
||||
}
|
||||
auto &childrenGroups = eventsBasedObject.GetObjects().GetObjectGroups();
|
||||
for (size_t index = 0; index < childrenGroups.Count(); ++index) {
|
||||
auto &childGroup = childrenGroups.Get(index);
|
||||
outputObjectsContainer.GetObjectGroups().Insert(
|
||||
childGroup, outputObjectsContainer.GetObjectGroups().Count());
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -35,7 +35,7 @@ class GD_CORE_API EventsFunctionTools {
|
||||
*/
|
||||
static void FreeEventsFunctionToObjectsContainer(
|
||||
const gd::Project& project,
|
||||
const gd::EventsFunctionsContainer functionContainer,
|
||||
const gd::EventsFunctionsContainer& functionContainer,
|
||||
const gd::EventsFunction& eventsFunction,
|
||||
gd::ObjectsContainer& outputObjectsContainer);
|
||||
|
||||
@@ -68,5 +68,9 @@ class GD_CORE_API EventsFunctionTools {
|
||||
const gd::EventsBasedObject& eventsBasedObject,
|
||||
const gd::EventsFunction& eventsFunction,
|
||||
gd::ObjectsContainer& outputObjectsContainer);
|
||||
|
||||
static void CopyEventsBasedObjectChildrenToObjectsContainer(
|
||||
const gd::EventsBasedObject &eventsBasedObject,
|
||||
gd::ObjectsContainer &outputObjectsContainer);
|
||||
};
|
||||
} // namespace gd
|
||||
|
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* GDevelop JS Platform
|
||||
* Copyright 2008-2023 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#include "EventsBasedObjectDependencyFinder.h"
|
||||
|
||||
#include "GDCore/Project/EventsBasedObject.h"
|
||||
#include "GDCore/Project/Object.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
|
||||
namespace gd {
|
||||
bool EventsBasedObjectDependencyFinder::IsDependentFromEventsBasedObject(
|
||||
const gd::Project &project, const gd::EventsBasedObject &eventsBasedObject,
|
||||
const gd::EventsBasedObject &dependency) {
|
||||
return gd::EventsBasedObjectDependencyFinder::
|
||||
IsDependentFromEventsBasedObject(project, eventsBasedObject, dependency,
|
||||
0);
|
||||
}
|
||||
bool EventsBasedObjectDependencyFinder::IsDependentFromEventsBasedObject(
|
||||
const gd::Project &project, const gd::EventsBasedObject &eventsBasedObject,
|
||||
const gd::EventsBasedObject &dependency, int depth) {
|
||||
|
||||
if (&eventsBasedObject == &dependency) {
|
||||
return true;
|
||||
}
|
||||
if (depth > 200) {
|
||||
return false;
|
||||
}
|
||||
for (auto &object : eventsBasedObject.GetObjects().GetObjects()) {
|
||||
const gd::String &objectType = object->GetType();
|
||||
if (project.HasEventsBasedObject(objectType) &&
|
||||
gd::EventsBasedObjectDependencyFinder::IsDependentFromEventsBasedObject(
|
||||
project, project.GetEventsBasedObject(objectType), dependency,
|
||||
depth + 1)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} // namespace gd
|
37
Core/GDCore/IDE/Project/EventsBasedObjectDependencyFinder.h
Normal file
37
Core/GDCore/IDE/Project/EventsBasedObjectDependencyFinder.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* GDevelop JS Platform
|
||||
* Copyright 2008-2023 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GDCore/String.h"
|
||||
|
||||
namespace gd {
|
||||
class Project;
|
||||
class EventsBasedObject;
|
||||
} // namespace gd
|
||||
|
||||
namespace gd {
|
||||
|
||||
/**
|
||||
* \brief Find resource usages in several parts of the project.
|
||||
*
|
||||
* \ingroup IDE
|
||||
*/
|
||||
class EventsBasedObjectDependencyFinder {
|
||||
public:
|
||||
static bool IsDependentFromEventsBasedObject(
|
||||
const gd::Project &project,
|
||||
const gd::EventsBasedObject &eventsBasedObject,
|
||||
const gd::EventsBasedObject &dependency);
|
||||
|
||||
private:
|
||||
static bool IsDependentFromEventsBasedObject(
|
||||
const gd::Project &project,
|
||||
const gd::EventsBasedObject &eventsBasedObject,
|
||||
const gd::EventsBasedObject &dependency, int depth);
|
||||
};
|
||||
|
||||
} // namespace gd
|
@@ -250,7 +250,7 @@ void ProjectBrowserHelper::ExposeProjectObjects(
|
||||
gd::Project &project, gd::ArbitraryObjectsWorker &worker) {
|
||||
|
||||
// Global objects
|
||||
worker.Launch(project);
|
||||
worker.Launch(project.GetObjects());
|
||||
|
||||
// Layout objects
|
||||
for (size_t i = 0; i < project.GetLayoutsCount(); i++) {
|
||||
@@ -265,7 +265,7 @@ void ProjectBrowserHelper::ExposeProjectObjects(
|
||||
for (auto &&eventsBasedObjectUniquePtr :
|
||||
eventsFunctionsExtension.GetEventsBasedObjects().GetInternalVector()) {
|
||||
auto eventsBasedObject = eventsBasedObjectUniquePtr.get();
|
||||
worker.Launch(*eventsBasedObject);
|
||||
worker.Launch(eventsBasedObject->GetObjects());
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -275,7 +275,7 @@ void ProjectBrowserHelper::ExposeLayoutObjects(gd::Layout &layout,
|
||||
// In the future, layouts may have children object containers.
|
||||
|
||||
// Layout objects
|
||||
worker.Launch(layout);
|
||||
worker.Launch(layout.GetObjects());
|
||||
}
|
||||
|
||||
void ProjectBrowserHelper::ExposeProjectFunctions(
|
||||
|
@@ -17,7 +17,7 @@
|
||||
namespace gd {
|
||||
|
||||
void GD_CORE_API ProjectStripper::StripProjectForExport(gd::Project &project) {
|
||||
project.GetObjectGroups().Clear();
|
||||
project.GetObjects().GetObjectGroups().Clear();
|
||||
while (project.GetExternalEventsCount() > 0)
|
||||
project.RemoveExternalEvents(project.GetExternalEvents(0).GetName());
|
||||
|
||||
@@ -26,7 +26,7 @@ void GD_CORE_API ProjectStripper::StripProjectForExport(gd::Project &project) {
|
||||
wholeProjectBrowser.ExposeObjects(project, behaviorDefaultFlagClearer);
|
||||
|
||||
for (unsigned int i = 0; i < project.GetLayoutsCount(); ++i) {
|
||||
project.GetLayout(i).GetObjectGroups().Clear();
|
||||
project.GetLayout(i).GetObjects().GetObjectGroups().Clear();
|
||||
project.GetLayout(i).GetEvents().Clear();
|
||||
}
|
||||
|
||||
|
@@ -76,7 +76,7 @@ void ResourceExposer::ExposeWholeProjectResources(gd::Project& project, gd::Arbi
|
||||
void ResourceExposer::ExposeProjectResources(gd::Project& project, gd::ArbitraryResourceWorker& worker) {
|
||||
// Expose global objects configuration resources
|
||||
auto objectWorker = gd::GetResourceWorkerOnObjects(project, worker);
|
||||
objectWorker.Launch(project);
|
||||
objectWorker.Launch(project.GetObjects());
|
||||
}
|
||||
|
||||
void ResourceExposer::ExposeLayoutResources(
|
||||
|
@@ -86,10 +86,10 @@ WholeProjectRefactorer::GetAllObjectTypesUsingEventsBasedBehavior(
|
||||
}
|
||||
};
|
||||
|
||||
addTypesOfObjectsIn(project);
|
||||
addTypesOfObjectsIn(project.GetObjects());
|
||||
for (std::size_t s = 0; s < project.GetLayoutsCount(); s++) {
|
||||
auto &layout = project.GetLayout(s);
|
||||
addTypesOfObjectsIn(layout);
|
||||
addTypesOfObjectsIn(layout.GetObjects());
|
||||
}
|
||||
|
||||
return allTypes;
|
||||
@@ -1177,12 +1177,14 @@ WholeProjectRefactorer::FindInvalidRequiredBehaviorProperties(
|
||||
};
|
||||
|
||||
// Find in global objects
|
||||
findInvalidRequiredBehaviorPropertiesInObjects(project.GetObjects());
|
||||
findInvalidRequiredBehaviorPropertiesInObjects(
|
||||
project.GetObjects().GetObjects());
|
||||
|
||||
// Find in layout objects.
|
||||
for (std::size_t i = 0; i < project.GetLayoutsCount(); ++i) {
|
||||
const gd::Layout &layout = project.GetLayout(i);
|
||||
findInvalidRequiredBehaviorPropertiesInObjects(layout.GetObjects());
|
||||
findInvalidRequiredBehaviorPropertiesInObjects(
|
||||
layout.GetObjects().GetObjects());
|
||||
}
|
||||
return invalidRequiredBehaviorProperties;
|
||||
}
|
||||
@@ -1521,10 +1523,10 @@ void WholeProjectRefactorer::ObjectRemovedInLayout(
|
||||
auto projectScopedContainers = gd::ProjectScopedContainers::
|
||||
MakeNewProjectScopedContainersForProjectAndLayout(project, layout);
|
||||
|
||||
// Object groups can't have instances or be in other groups
|
||||
for (std::size_t g = 0; g < layout.GetObjectGroups().size(); ++g) {
|
||||
if (layout.GetObjectGroups()[g].Find(objectName))
|
||||
layout.GetObjectGroups()[g].RemoveObject(objectName);
|
||||
auto &groups = layout.GetObjects().GetObjectGroups();
|
||||
for (std::size_t g = 0; g < groups.size(); ++g) {
|
||||
if (groups[g].Find(objectName))
|
||||
groups[g].RemoveObject(objectName);
|
||||
}
|
||||
layout.GetInitialInstances().RemoveInitialInstancesOfObject(objectName);
|
||||
|
||||
@@ -1562,11 +1564,12 @@ void WholeProjectRefactorer::ObjectOrGroupRenamedInLayout(
|
||||
project.GetCurrentPlatform(), projectScopedContainers, layout.GetEvents(),
|
||||
oldName, newName);
|
||||
|
||||
if (!isObjectGroup) { // Object groups can't have instances or be in other
|
||||
// groups
|
||||
// Object groups can't have instances or be in other groups
|
||||
if (!isObjectGroup) {
|
||||
auto &groups = layout.GetObjects().GetObjectGroups();
|
||||
layout.GetInitialInstances().RenameInstancesOfObject(oldName, newName);
|
||||
for (std::size_t g = 0; g < layout.GetObjectGroups().size(); ++g) {
|
||||
layout.GetObjectGroups()[g].RenameObject(oldName, newName);
|
||||
for (std::size_t g = 0; g < groups.size(); ++g) {
|
||||
groups[g].RenameObject(oldName, newName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1717,54 +1720,62 @@ void WholeProjectRefactorer::RenameObjectEffect(gd::Project &project,
|
||||
|
||||
void WholeProjectRefactorer::ObjectRemovedInEventsBasedObject(
|
||||
gd::Project &project, gd::EventsBasedObject &eventsBasedObject,
|
||||
gd::ObjectsContainer &globalObjectsContainer,
|
||||
gd::ObjectsContainer &objectsContainer, const gd::String &objectName) {
|
||||
const gd::String &objectName) {
|
||||
for (auto &functionUniquePtr :
|
||||
eventsBasedObject.GetEventsFunctions().GetInternalVector()) {
|
||||
auto function = functionUniquePtr.get();
|
||||
WholeProjectRefactorer::ObjectRemovedInEventsFunction(
|
||||
project, *function, globalObjectsContainer, objectsContainer,
|
||||
objectName);
|
||||
WholeProjectRefactorer::ObjectRemovedInEventsFunction(project, *function,
|
||||
objectName);
|
||||
}
|
||||
|
||||
auto &groups = eventsBasedObject.GetObjects().GetObjectGroups();
|
||||
for (std::size_t g = 0; g < groups.size(); ++g) {
|
||||
if (groups[g].Find(objectName))
|
||||
groups[g].RemoveObject(objectName);
|
||||
}
|
||||
eventsBasedObject.GetInitialInstances().RemoveInitialInstancesOfObject(
|
||||
objectName);
|
||||
}
|
||||
|
||||
void WholeProjectRefactorer::ObjectRemovedInEventsFunction(
|
||||
gd::Project &project, gd::EventsFunction &eventsFunction,
|
||||
gd::ObjectsContainer &globalObjectsContainer,
|
||||
gd::ObjectsContainer &objectsContainer, const gd::String &objectName) {
|
||||
const gd::String &objectName) {
|
||||
|
||||
for (std::size_t g = 0; g < eventsFunction.GetObjectGroups().size();
|
||||
++g) {
|
||||
for (std::size_t g = 0; g < eventsFunction.GetObjectGroups().size(); ++g) {
|
||||
if (eventsFunction.GetObjectGroups()[g].Find(objectName))
|
||||
eventsFunction.GetObjectGroups()[g].RemoveObject(objectName);
|
||||
}
|
||||
}
|
||||
|
||||
void WholeProjectRefactorer::ObjectOrGroupRenamedInEventsBasedObject(
|
||||
gd::Project &project, gd::ObjectsContainer &globalObjectsContainer,
|
||||
gd::Project &project,
|
||||
const gd::ProjectScopedContainers &projectScopedContainers,
|
||||
gd::EventsBasedObject &eventsBasedObject, const gd::String &oldName,
|
||||
const gd::String &newName, bool isObjectGroup) {
|
||||
for (auto &functionUniquePtr :
|
||||
eventsBasedObject.GetEventsFunctions().GetInternalVector()) {
|
||||
auto *function = functionUniquePtr.get();
|
||||
WholeProjectRefactorer::ObjectOrGroupRenamedInEventsFunction(
|
||||
project, *function, globalObjectsContainer, eventsBasedObject, oldName,
|
||||
newName, isObjectGroup);
|
||||
project, projectScopedContainers, *function, oldName, newName,
|
||||
isObjectGroup);
|
||||
}
|
||||
|
||||
// Object groups can't have instances or be in other groups
|
||||
if (!isObjectGroup) {
|
||||
eventsBasedObject.GetInitialInstances().RenameInstancesOfObject(oldName,
|
||||
newName);
|
||||
auto &groups = eventsBasedObject.GetObjects().GetObjectGroups();
|
||||
for (std::size_t g = 0; g < groups.size(); ++g) {
|
||||
groups[g].RenameObject(oldName, newName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WholeProjectRefactorer::ObjectOrGroupRenamedInEventsFunction(
|
||||
gd::Project &project, gd::EventsFunction &eventsFunction,
|
||||
gd::ObjectsContainer &globalObjectsContainer,
|
||||
gd::ObjectsContainer &objectsContainer, const gd::String &oldName,
|
||||
gd::Project &project,
|
||||
const gd::ProjectScopedContainers &projectScopedContainers,
|
||||
gd::EventsFunction &eventsFunction, const gd::String &oldName,
|
||||
const gd::String &newName, bool isObjectGroup) {
|
||||
// In theory we should pass a ProjectScopedContainers to this function so it
|
||||
// does not have to construct one. In practice, this is ok because we only
|
||||
// deal with objects.
|
||||
auto projectScopedContainers =
|
||||
gd::ProjectScopedContainers::MakeNewProjectScopedContainersFor(
|
||||
globalObjectsContainer, objectsContainer);
|
||||
|
||||
gd::EventsRefactorer::RenameObjectInEvents(
|
||||
project.GetCurrentPlatform(), projectScopedContainers,
|
||||
eventsFunction.GetEvents(), oldName, newName);
|
||||
@@ -1782,14 +1793,16 @@ void WholeProjectRefactorer::GlobalObjectOrGroupRenamed(
|
||||
bool isObjectGroup) {
|
||||
// Object groups can't be in other groups
|
||||
if (!isObjectGroup) {
|
||||
for (std::size_t g = 0; g < project.GetObjectGroups().size(); ++g) {
|
||||
project.GetObjectGroups()[g].RenameObject(oldName, newName);
|
||||
for (std::size_t g = 0;
|
||||
g < project.GetObjects().GetObjectGroups().size(); ++g) {
|
||||
project.GetObjects().GetObjectGroups()[g].RenameObject(oldName,
|
||||
newName);
|
||||
}
|
||||
}
|
||||
|
||||
for (std::size_t i = 0; i < project.GetLayoutsCount(); ++i) {
|
||||
gd::Layout &layout = project.GetLayout(i);
|
||||
if (layout.HasObjectNamed(oldName))
|
||||
if (layout.GetObjects().HasObjectNamed(oldName))
|
||||
continue;
|
||||
|
||||
ObjectOrGroupRenamedInLayout(project, layout, oldName, newName,
|
||||
@@ -1799,13 +1812,14 @@ void WholeProjectRefactorer::GlobalObjectOrGroupRenamed(
|
||||
|
||||
void WholeProjectRefactorer::GlobalObjectRemoved(
|
||||
gd::Project &project, const gd::String &objectName) {
|
||||
for (std::size_t g = 0; g < project.GetObjectGroups().size(); ++g) {
|
||||
project.GetObjectGroups()[g].RemoveObject(objectName);
|
||||
auto &globalGroups = project.GetObjects().GetObjectGroups();
|
||||
for (std::size_t g = 0; g < globalGroups.size(); ++g) {
|
||||
globalGroups[g].RemoveObject(objectName);
|
||||
}
|
||||
|
||||
for (std::size_t i = 0; i < project.GetLayoutsCount(); ++i) {
|
||||
gd::Layout &layout = project.GetLayout(i);
|
||||
if (layout.HasObjectNamed(objectName))
|
||||
if (layout.GetObjects().HasObjectNamed(objectName))
|
||||
continue;
|
||||
|
||||
ObjectRemovedInLayout(project, layout, objectName);
|
||||
@@ -1816,41 +1830,41 @@ void WholeProjectRefactorer::BehaviorsAddedToGlobalObject(
|
||||
gd::Project &project, const gd::String &objectName) {
|
||||
for (std::size_t i = 0; i < project.GetLayoutsCount(); ++i) {
|
||||
gd::Layout &layout = project.GetLayout(i);
|
||||
if (layout.HasObjectNamed(objectName))
|
||||
if (layout.GetObjects().HasObjectNamed(objectName))
|
||||
continue;
|
||||
|
||||
BehaviorsAddedToObjectInLayout(project, layout, objectName);
|
||||
}
|
||||
}
|
||||
|
||||
void WholeProjectRefactorer::RemoveLayer(gd::Project &project,
|
||||
gd::Layout &layout,
|
||||
void WholeProjectRefactorer::RemoveLayerInScene(gd::Project &project,
|
||||
gd::Layout &scene,
|
||||
const gd::String &layerName) {
|
||||
if (layerName.empty())
|
||||
return;
|
||||
|
||||
layout.GetInitialInstances().RemoveAllInstancesOnLayer(layerName);
|
||||
scene.GetInitialInstances().RemoveAllInstancesOnLayer(layerName);
|
||||
|
||||
std::vector<gd::String> externalLayoutsNames =
|
||||
GetAssociatedExternalLayouts(project, layout);
|
||||
GetAssociatedExternalLayouts(project, scene);
|
||||
for (gd::String name : externalLayoutsNames) {
|
||||
auto &externalLayout = project.GetExternalLayout(name);
|
||||
externalLayout.GetInitialInstances().RemoveAllInstancesOnLayer(layerName);
|
||||
}
|
||||
}
|
||||
|
||||
void WholeProjectRefactorer::MergeLayers(gd::Project &project,
|
||||
gd::Layout &layout,
|
||||
void WholeProjectRefactorer::MergeLayersInScene(gd::Project &project,
|
||||
gd::Layout &scene,
|
||||
const gd::String &originLayerName,
|
||||
const gd::String &targetLayerName) {
|
||||
if (originLayerName == targetLayerName || originLayerName.empty())
|
||||
return;
|
||||
|
||||
layout.GetInitialInstances().MoveInstancesToLayer(originLayerName,
|
||||
scene.GetInitialInstances().MoveInstancesToLayer(originLayerName,
|
||||
targetLayerName);
|
||||
|
||||
std::vector<gd::String> externalLayoutsNames =
|
||||
GetAssociatedExternalLayouts(project, layout);
|
||||
GetAssociatedExternalLayouts(project, scene);
|
||||
for (gd::String name : externalLayoutsNames) {
|
||||
auto &externalLayout = project.GetExternalLayout(name);
|
||||
externalLayout.GetInitialInstances().MoveInstancesToLayer(originLayerName,
|
||||
@@ -1858,6 +1872,24 @@ void WholeProjectRefactorer::MergeLayers(gd::Project &project,
|
||||
}
|
||||
}
|
||||
|
||||
void WholeProjectRefactorer::RemoveLayerInEventsBasedObject(
|
||||
gd::EventsBasedObject &eventsBasedObject, const gd::String &layerName) {
|
||||
if (layerName.empty())
|
||||
return;
|
||||
|
||||
eventsBasedObject.GetInitialInstances().RemoveAllInstancesOnLayer(layerName);
|
||||
}
|
||||
|
||||
void WholeProjectRefactorer::MergeLayersInEventsBasedObject(
|
||||
gd::EventsBasedObject &eventsBasedObject, const gd::String &originLayerName,
|
||||
const gd::String &targetLayerName) {
|
||||
if (originLayerName == targetLayerName || originLayerName.empty())
|
||||
return;
|
||||
|
||||
eventsBasedObject.GetInitialInstances().MoveInstancesToLayer(originLayerName,
|
||||
targetLayerName);
|
||||
}
|
||||
|
||||
size_t WholeProjectRefactorer::GetLayoutAndExternalLayoutLayerInstancesCount(
|
||||
gd::Project &project, gd::Layout &layout, const gd::String &layerName) {
|
||||
size_t count = layout.GetInitialInstances().GetLayerInstancesCount(layerName);
|
||||
|
@@ -37,6 +37,7 @@ class BehaviorMetadata;
|
||||
class UnfilledRequiredBehaviorPropertyProblem;
|
||||
class ProjectBrowser;
|
||||
class SerializerElement;
|
||||
class ProjectScopedContainers;
|
||||
struct VariablesRenamingChangesetNode;
|
||||
} // namespace gd
|
||||
|
||||
@@ -416,8 +417,6 @@ class GD_CORE_API WholeProjectRefactorer {
|
||||
static void ObjectRemovedInEventsBasedObject(
|
||||
gd::Project& project,
|
||||
gd::EventsBasedObject& eventsBasedObject,
|
||||
gd::ObjectsContainer& globalObjectsContainer,
|
||||
gd::ObjectsContainer& objectsContainer,
|
||||
const gd::String& objectName);
|
||||
|
||||
/**
|
||||
@@ -427,7 +426,7 @@ class GD_CORE_API WholeProjectRefactorer {
|
||||
*/
|
||||
static void ObjectOrGroupRenamedInEventsBasedObject(
|
||||
gd::Project& project,
|
||||
gd::ObjectsContainer& globalObjectsContainer,
|
||||
const gd::ProjectScopedContainers &projectScopedContainers,
|
||||
gd::EventsBasedObject& eventsBasedObject,
|
||||
const gd::String& oldName,
|
||||
const gd::String& newName,
|
||||
@@ -440,9 +439,8 @@ class GD_CORE_API WholeProjectRefactorer {
|
||||
*/
|
||||
static void ObjectOrGroupRenamedInEventsFunction(
|
||||
gd::Project& project,
|
||||
const gd::ProjectScopedContainers &projectScopedContainers,
|
||||
gd::EventsFunction& eventsFunction,
|
||||
gd::ObjectsContainer& globalObjectsContainer,
|
||||
gd::ObjectsContainer& objectsContainer,
|
||||
const gd::String& oldName,
|
||||
const gd::String& newName,
|
||||
bool isObjectGroup);
|
||||
@@ -455,8 +453,6 @@ class GD_CORE_API WholeProjectRefactorer {
|
||||
static void ObjectRemovedInEventsFunction(
|
||||
gd::Project& project,
|
||||
gd::EventsFunction& eventsFunction,
|
||||
gd::ObjectsContainer& globalObjectsContainer,
|
||||
gd::ObjectsContainer& objectsContainer,
|
||||
const gd::String& objectName);
|
||||
|
||||
/**
|
||||
@@ -518,16 +514,31 @@ class GD_CORE_API WholeProjectRefactorer {
|
||||
/**
|
||||
* \brief Remove all the instances from one layer.
|
||||
*/
|
||||
static void RemoveLayer(gd::Project &project, gd::Layout &layout,
|
||||
static void RemoveLayerInScene(gd::Project &project, gd::Layout &scene,
|
||||
const gd::String &layerName);
|
||||
|
||||
/**
|
||||
* \brief Move all the instances from one layer into another.
|
||||
*/
|
||||
static void MergeLayers(gd::Project &project, gd::Layout &layout,
|
||||
static void MergeLayersInScene(gd::Project &project, gd::Layout &scene,
|
||||
const gd::String &originLayerName,
|
||||
const gd::String &targetLayerName);
|
||||
|
||||
/**
|
||||
* \brief Remove all the instances from one layer.
|
||||
*/
|
||||
static void
|
||||
RemoveLayerInEventsBasedObject(gd::EventsBasedObject &eventsBasedObject,
|
||||
const gd::String &layerName);
|
||||
|
||||
/**
|
||||
* \brief Move all the instances from one layer into another.
|
||||
*/
|
||||
static void
|
||||
MergeLayersInEventsBasedObject(gd::EventsBasedObject &eventsBasedObject,
|
||||
const gd::String &originLayerName,
|
||||
const gd::String &targetLayerName);
|
||||
|
||||
/**
|
||||
* \brief Return the number of instances on the layer named \a layerName and
|
||||
* all its associated layouts.
|
||||
|
@@ -35,19 +35,26 @@ std::unique_ptr<gd::ObjectConfiguration> CustomObjectConfiguration::Clone() cons
|
||||
return gd::make_unique<gd::CustomObjectConfiguration>(*this);
|
||||
}
|
||||
|
||||
gd::ObjectConfiguration &CustomObjectConfiguration::GetChildObjectConfiguration(const gd::String &objectName) {
|
||||
const gd::EventsBasedObject* CustomObjectConfiguration::GetEventsBasedObject() const {
|
||||
if (!project->HasEventsBasedObject(GetType())) {
|
||||
return nullptr;
|
||||
}
|
||||
return &project->GetEventsBasedObject(GetType());
|
||||
}
|
||||
|
||||
gd::ObjectConfiguration &CustomObjectConfiguration::GetChildObjectConfiguration(const gd::String &objectName) {
|
||||
const auto *eventsBasedObject = GetEventsBasedObject();
|
||||
if (!eventsBasedObject) {
|
||||
return badObjectConfiguration;
|
||||
}
|
||||
const auto &eventsBasedObject = project->GetEventsBasedObject(GetType());
|
||||
|
||||
if (!eventsBasedObject.HasObjectNamed(objectName)) {
|
||||
if (!eventsBasedObject->GetObjects().HasObjectNamed(objectName)) {
|
||||
gd::LogError("Tried to get the configuration of a child-object:" + objectName
|
||||
+ " that doesn't exist in the event-based object: " + GetType());
|
||||
return badObjectConfiguration;
|
||||
}
|
||||
|
||||
auto &childObject = eventsBasedObject.GetObject(objectName);
|
||||
auto &childObject = eventsBasedObject->GetObjects().GetObject(objectName);
|
||||
auto configurationPosition = childObjectConfigurations.find(objectName);
|
||||
if (configurationPosition == childObjectConfigurations.end()) {
|
||||
childObjectConfigurations.insert(std::make_pair(
|
||||
@@ -90,8 +97,7 @@ bool CustomObjectConfiguration::UpdateProperty(const gd::String& propertyName,
|
||||
|
||||
std::map<gd::String, gd::PropertyDescriptor>
|
||||
CustomObjectConfiguration::GetInitialInstanceProperties(
|
||||
const gd::InitialInstance &initialInstance, gd::Project &project,
|
||||
gd::Layout &scene) {
|
||||
const gd::InitialInstance &initialInstance) {
|
||||
std::map<gd::String, gd::PropertyDescriptor> properties;
|
||||
if (!animations.HasNoAnimations()) {
|
||||
properties["animation"] =
|
||||
@@ -105,7 +111,7 @@ CustomObjectConfiguration::GetInitialInstanceProperties(
|
||||
|
||||
bool CustomObjectConfiguration::UpdateInitialInstanceProperty(
|
||||
gd::InitialInstance &initialInstance, const gd::String &name,
|
||||
const gd::String &value, gd::Project &project, gd::Layout &scene) {
|
||||
const gd::String &value) {
|
||||
if (name == "animation") {
|
||||
initialInstance.SetRawDoubleProperty(
|
||||
"animation", std::max(0, value.empty() ? 0 : value.To<int>()));
|
||||
@@ -129,6 +135,20 @@ void CustomObjectConfiguration::DoSerializeTo(SerializerElement& element) const
|
||||
auto &childElement = childrenContentElement.AddChild(childName);
|
||||
childConfiguration->SerializeTo(childElement);
|
||||
}
|
||||
|
||||
const auto *eventsBasedObject = GetEventsBasedObject();
|
||||
if (eventsBasedObject) {
|
||||
eventsBasedObject->GetInitialInstances().SerializeTo(
|
||||
element.AddChild("instances"));
|
||||
eventsBasedObject->GetLayers().SerializeLayersTo(
|
||||
element.AddChild("layers"));
|
||||
element.SetIntAttribute("areaMinX", eventsBasedObject->GetAreaMinX());
|
||||
element.SetIntAttribute("areaMinY", eventsBasedObject->GetAreaMinY());
|
||||
element.SetIntAttribute("areaMinZ", eventsBasedObject->GetAreaMinZ());
|
||||
element.SetIntAttribute("areaMaxX", eventsBasedObject->GetAreaMaxX());
|
||||
element.SetIntAttribute("areaMaxY", eventsBasedObject->GetAreaMaxY());
|
||||
element.SetIntAttribute("areaMaxZ", eventsBasedObject->GetAreaMaxZ());
|
||||
}
|
||||
}
|
||||
void CustomObjectConfiguration::DoUnserializeFrom(Project& project,
|
||||
const SerializerElement& element) {
|
||||
@@ -198,7 +218,7 @@ void CustomObjectConfiguration::ExposeResources(gd::ArbitraryResourceWorker& wor
|
||||
}
|
||||
const auto &eventsBasedObject = project->GetEventsBasedObject(GetType());
|
||||
|
||||
for (auto& childObject : eventsBasedObject.GetObjects()) {
|
||||
for (auto& childObject : eventsBasedObject.GetObjects().GetObjects()) {
|
||||
auto &configuration = GetChildObjectConfiguration(childObject->GetName());
|
||||
configuration.ExposeResources(worker);
|
||||
}
|
||||
|
@@ -58,14 +58,10 @@ class CustomObjectConfiguration : public gd::ObjectConfiguration {
|
||||
bool UpdateProperty(const gd::String& name, const gd::String& value) override;
|
||||
|
||||
std::map<gd::String, gd::PropertyDescriptor> GetInitialInstanceProperties(
|
||||
const gd::InitialInstance& instance,
|
||||
gd::Project& project,
|
||||
gd::Layout& scene) override;
|
||||
const gd::InitialInstance& instance) override;
|
||||
bool UpdateInitialInstanceProperty(gd::InitialInstance& instance,
|
||||
const gd::String& name,
|
||||
const gd::String& value,
|
||||
gd::Project& project,
|
||||
gd::Layout& scene) override;
|
||||
const gd::String& value) override;
|
||||
|
||||
void ExposeResources(gd::ArbitraryResourceWorker& worker) override;
|
||||
|
||||
@@ -86,6 +82,8 @@ protected:
|
||||
void DoUnserializeFrom(Project& project, const SerializerElement& element) override;
|
||||
|
||||
private:
|
||||
const gd::EventsBasedObject* GetEventsBasedObject() const;
|
||||
|
||||
const Project* project; ///< The project is used to get the
|
||||
///< EventBasedObject from the fullType.
|
||||
gd::SerializerElement objectContent;
|
||||
|
@@ -13,21 +13,19 @@ EventsBasedObject::EventsBasedObject()
|
||||
: AbstractEventsBasedEntity(
|
||||
"MyObject",
|
||||
gd::EventsFunctionsContainer::FunctionOwner::Object),
|
||||
ObjectsContainer(),
|
||||
isRenderedIn3D(false),
|
||||
isAnimatable(false),
|
||||
isTextContainer(false) {
|
||||
isTextContainer(false),
|
||||
areaMinX(0),
|
||||
areaMinY(0),
|
||||
areaMinZ(0),
|
||||
areaMaxX(64),
|
||||
areaMaxY(64),
|
||||
areaMaxZ(64) {
|
||||
}
|
||||
|
||||
EventsBasedObject::~EventsBasedObject() {}
|
||||
|
||||
EventsBasedObject::EventsBasedObject(const gd::EventsBasedObject &_eventBasedObject)
|
||||
: AbstractEventsBasedEntity(_eventBasedObject) {
|
||||
// TODO Add a copy constructor in ObjectsContainer.
|
||||
initialObjects = gd::Clone(_eventBasedObject.initialObjects);
|
||||
objectGroups = _eventBasedObject.objectGroups;
|
||||
}
|
||||
|
||||
void EventsBasedObject::SerializeTo(SerializerElement& element) const {
|
||||
element.SetAttribute("defaultName", defaultName);
|
||||
if (isRenderedIn3D) {
|
||||
@@ -39,10 +37,20 @@ void EventsBasedObject::SerializeTo(SerializerElement& element) const {
|
||||
if (isTextContainer) {
|
||||
element.SetBoolAttribute("isTextContainer", true);
|
||||
}
|
||||
element.SetIntAttribute("areaMinX", areaMinX);
|
||||
element.SetIntAttribute("areaMinY", areaMinY);
|
||||
element.SetIntAttribute("areaMinZ", areaMinZ);
|
||||
element.SetIntAttribute("areaMaxX", areaMaxX);
|
||||
element.SetIntAttribute("areaMaxY", areaMaxY);
|
||||
element.SetIntAttribute("areaMaxZ", areaMaxZ);
|
||||
|
||||
AbstractEventsBasedEntity::SerializeTo(element);
|
||||
SerializeObjectsTo(element.AddChild("objects"));
|
||||
SerializeFoldersTo(element.AddChild("objectsFolderStructure"));
|
||||
objectsContainer.SerializeObjectsTo(element.AddChild("objects"));
|
||||
objectsContainer.SerializeFoldersTo(element.AddChild("objectsFolderStructure"));
|
||||
objectsContainer.GetObjectGroups().SerializeTo(element.AddChild("objectsGroups"));
|
||||
|
||||
layers.SerializeLayersTo(element.AddChild("layers"));
|
||||
initialInstances.SerializeTo(element.AddChild("instances"));
|
||||
}
|
||||
|
||||
void EventsBasedObject::UnserializeFrom(gd::Project& project,
|
||||
@@ -51,13 +59,29 @@ void EventsBasedObject::UnserializeFrom(gd::Project& project,
|
||||
isRenderedIn3D = element.GetBoolAttribute("is3D", false);
|
||||
isAnimatable = element.GetBoolAttribute("isAnimatable", false);
|
||||
isTextContainer = element.GetBoolAttribute("isTextContainer", false);
|
||||
areaMinX = element.GetIntAttribute("areaMinX", 0);
|
||||
areaMinY = element.GetIntAttribute("areaMinY", 0);
|
||||
areaMinZ = element.GetIntAttribute("areaMinZ", 0);
|
||||
areaMaxX = element.GetIntAttribute("areaMaxX", 64);
|
||||
areaMaxY = element.GetIntAttribute("areaMaxY", 64);
|
||||
areaMaxZ = element.GetIntAttribute("areaMaxZ", 64);
|
||||
|
||||
AbstractEventsBasedEntity::UnserializeFrom(project, element);
|
||||
UnserializeObjectsFrom(project, element.GetChild("objects"));
|
||||
objectsContainer.UnserializeObjectsFrom(project, element.GetChild("objects"));
|
||||
if (element.HasChild("objectsFolderStructure")) {
|
||||
UnserializeFoldersFrom(project, element.GetChild("objectsFolderStructure", 0));
|
||||
objectsContainer.UnserializeFoldersFrom(project, element.GetChild("objectsFolderStructure", 0));
|
||||
}
|
||||
AddMissingObjectsInRootFolder();
|
||||
objectsContainer.AddMissingObjectsInRootFolder();
|
||||
objectsContainer.GetObjectGroups().UnserializeFrom(
|
||||
element.GetChild("objectsGroups"));
|
||||
|
||||
if (element.HasChild("layers")) {
|
||||
layers.UnserializeLayersFrom(element.GetChild("layers"));
|
||||
} else {
|
||||
layers.Reset();
|
||||
}
|
||||
|
||||
initialInstances.UnserializeFrom(element.GetChild("instances"));
|
||||
}
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -3,12 +3,13 @@
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#ifndef GDCORE_EVENTSBASEDOBJECT_H
|
||||
#define GDCORE_EVENTSBASEDOBJECT_H
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "GDCore/Project/AbstractEventsBasedEntity.h"
|
||||
#include "GDCore/Project/ObjectsContainer.h"
|
||||
#include "GDCore/Project/InitialInstancesContainer.h"
|
||||
#include "GDCore/Project/LayersContainer.h"
|
||||
#include "GDCore/String.h"
|
||||
namespace gd {
|
||||
class SerializerElement;
|
||||
@@ -26,11 +27,10 @@ namespace gd {
|
||||
*
|
||||
* \ingroup PlatformDefinition
|
||||
*/
|
||||
class GD_CORE_API EventsBasedObject: public AbstractEventsBasedEntity, public ObjectsContainer {
|
||||
class GD_CORE_API EventsBasedObject: public AbstractEventsBasedEntity {
|
||||
public:
|
||||
EventsBasedObject();
|
||||
virtual ~EventsBasedObject();
|
||||
EventsBasedObject(const gd::EventsBasedObject &_eventBasedObject);
|
||||
|
||||
/**
|
||||
* \brief Return a pointer to a new EventsBasedObject constructed from
|
||||
@@ -111,6 +111,164 @@ class GD_CORE_API EventsBasedObject: public AbstractEventsBasedEntity, public Ob
|
||||
*/
|
||||
bool IsTextContainer() const { return isTextContainer; }
|
||||
|
||||
/** \name Layers
|
||||
*/
|
||||
///@{
|
||||
/**
|
||||
* \brief Get the layers of the custom object.
|
||||
*/
|
||||
const gd::LayersContainer& GetLayers() const { return layers; }
|
||||
|
||||
/**
|
||||
* \brief Get the layers of the custom object.
|
||||
*/
|
||||
gd::LayersContainer& GetLayers() { return layers; }
|
||||
///@}
|
||||
|
||||
/** \name Child objects
|
||||
*/
|
||||
///@{
|
||||
/**
|
||||
* \brief Get the objects of the custom object.
|
||||
*/
|
||||
gd::ObjectsContainer& GetObjects() {
|
||||
return objectsContainer;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get the objects of the custom object.
|
||||
*/
|
||||
const gd::ObjectsContainer& GetObjects() const {
|
||||
return objectsContainer;
|
||||
}
|
||||
///@}
|
||||
|
||||
/** \name Instances
|
||||
*/
|
||||
///@{
|
||||
/**
|
||||
* \brief Get the instances of the custom object.
|
||||
*/
|
||||
gd::InitialInstancesContainer& GetInitialInstances() {
|
||||
return initialInstances;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get the instances of the custom object.
|
||||
*/
|
||||
const gd::InitialInstancesContainer& GetInitialInstances() const {
|
||||
return initialInstances;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get the left bound of the custom object.
|
||||
*
|
||||
* This is used only if there is any initial instances.
|
||||
*
|
||||
* \see EventsBasedObject::GetInitialInstances
|
||||
*/
|
||||
int GetAreaMinX() const {
|
||||
return areaMinX;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set the left bound of the custom object.
|
||||
*/
|
||||
void SetAreaMinX(int areaMinX_) {
|
||||
areaMinX = areaMinX_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get the top bound of the custom object.
|
||||
*
|
||||
* This is used only if there is any initial instances.
|
||||
*
|
||||
* \see EventsBasedObject::GetInitialInstances
|
||||
*/
|
||||
int GetAreaMinY() const {
|
||||
return areaMinY;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set the top bound of the custom object.
|
||||
*/
|
||||
void SetAreaMinY(int areaMinY_) {
|
||||
areaMinY = areaMinY_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get the min Z bound of the custom object.
|
||||
*
|
||||
* This is used only if there is any initial instances.
|
||||
*
|
||||
* \see EventsBasedObject::GetInitialInstances
|
||||
*/
|
||||
int GetAreaMinZ() const {
|
||||
return areaMinZ;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set the min Z bound of the custom object.
|
||||
*/
|
||||
void SetAreaMinZ(int areaMinZ_) {
|
||||
areaMinZ = areaMinZ_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get the right bound of the custom object.
|
||||
*
|
||||
* This is used only if there is any initial instances.
|
||||
*
|
||||
* \see EventsBasedObject::GetInitialInstances
|
||||
*/
|
||||
int GetAreaMaxX() const {
|
||||
return areaMaxX;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set the right bound of the custom object.
|
||||
*/
|
||||
void SetAreaMaxX(int areaMaxX_) {
|
||||
areaMaxX = areaMaxX_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get the bottom bound of the custom object.
|
||||
*
|
||||
* This is used only if there is any initial instances.
|
||||
*
|
||||
* \see EventsBasedObject::GetInitialInstances
|
||||
*/
|
||||
int GetAreaMaxY() const {
|
||||
return areaMaxY;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set the bottom bound of the custom object.
|
||||
*/
|
||||
void SetAreaMaxY(int areaMaxY_) {
|
||||
areaMaxY = areaMaxY_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get the max Z bound of the custom object.
|
||||
*
|
||||
* This is used only if there is any initial instances.
|
||||
*
|
||||
* \see EventsBasedObject::GetInitialInstances
|
||||
*/
|
||||
int GetAreaMaxZ() const {
|
||||
return areaMaxZ;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set the bottom bound of the custom object.
|
||||
*/
|
||||
void SetAreaMaxZ(int areaMaxZ_) {
|
||||
areaMaxZ = areaMaxZ_;
|
||||
}
|
||||
///@}
|
||||
|
||||
void SerializeTo(SerializerElement& element) const override;
|
||||
|
||||
void UnserializeFrom(gd::Project& project,
|
||||
@@ -121,8 +279,15 @@ class GD_CORE_API EventsBasedObject: public AbstractEventsBasedEntity, public Ob
|
||||
bool isRenderedIn3D;
|
||||
bool isAnimatable;
|
||||
bool isTextContainer;
|
||||
gd::InitialInstancesContainer initialInstances;
|
||||
gd::LayersContainer layers;
|
||||
gd::ObjectsContainer objectsContainer;
|
||||
double areaMinX;
|
||||
double areaMinY;
|
||||
double areaMinZ;
|
||||
double areaMaxX;
|
||||
double areaMaxY;
|
||||
double areaMaxZ;
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
||||
#endif // GDCORE_EVENTSBASEDOBJECT_H
|
||||
|
@@ -154,7 +154,7 @@ void EventsFunctionsExtension::UnserializeExtensionDeclarationFrom(
|
||||
for (size_t i = 0; i < dependenciesElement.GetChildrenCount(); ++i)
|
||||
dependencies.push_back(
|
||||
UnserializeDependencyFrom(dependenciesElement.GetChild(i)));
|
||||
|
||||
|
||||
globalVariables.UnserializeFrom(element.GetChild("globalVariables"));
|
||||
sceneVariables.UnserializeFrom(element.GetChild("sceneVariables"));
|
||||
|
||||
@@ -184,7 +184,11 @@ void EventsFunctionsExtension::UnserializeExtensionImplementationFrom(
|
||||
UnserializeEventsFunctionsFrom(project, element.GetChild("eventsFunctions"));
|
||||
eventsBasedBehaviors.UnserializeElementsFrom(
|
||||
"eventsBasedBehavior", project, element.GetChild("eventsBasedBehaviors"));
|
||||
eventsBasedObjects.UnserializeElementsFrom(
|
||||
|
||||
// It's important to load the objects without erasing them first as each object
|
||||
// might reference other objects, and so need to know if a custom object exists
|
||||
// in the project or not.
|
||||
eventsBasedObjects.ProgressivelyUnserializeElementsFrom(
|
||||
"eventsBasedObject", project, element.GetChild("eventsBasedObjects"));
|
||||
}
|
||||
|
||||
|
@@ -9,7 +9,6 @@
|
||||
#include "GDCore/IDE/Dialogs/LayoutEditorCanvas/EditorSettings.h"
|
||||
#include "GDCore/Project/InitialInstancesContainer.h"
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
#include "GDCore/TinyXml/tinyxml.h"
|
||||
|
||||
namespace gd {
|
||||
|
||||
|
@@ -8,6 +8,7 @@
|
||||
|
||||
#include "GDCore/Project/Layout.h"
|
||||
#include "GDCore/Project/Object.h"
|
||||
#include "GDCore/Project/ObjectsContainer.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/Project/PropertyDescriptor.h"
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
@@ -153,33 +154,35 @@ InitialInstance& InitialInstance::ResetPersistentUuid() {
|
||||
}
|
||||
|
||||
std::map<gd::String, gd::PropertyDescriptor>
|
||||
InitialInstance::GetCustomProperties(gd::Project& project, gd::Layout& layout) {
|
||||
InitialInstance::GetCustomProperties(
|
||||
gd::ObjectsContainer &globalObjectsContainer,
|
||||
gd::ObjectsContainer &objectsContainer) {
|
||||
// Find an object
|
||||
if (layout.HasObjectNamed(GetObjectName()))
|
||||
return layout.GetObject(GetObjectName())
|
||||
if (objectsContainer.HasObjectNamed(GetObjectName()))
|
||||
return objectsContainer.GetObject(GetObjectName())
|
||||
.GetConfiguration()
|
||||
.GetInitialInstanceProperties(*this, project, layout);
|
||||
else if (project.HasObjectNamed(GetObjectName()))
|
||||
return project.GetObject(GetObjectName())
|
||||
.GetInitialInstanceProperties(*this);
|
||||
else if (globalObjectsContainer.HasObjectNamed(GetObjectName()))
|
||||
return globalObjectsContainer.GetObject(GetObjectName())
|
||||
.GetConfiguration()
|
||||
.GetInitialInstanceProperties(*this, project, layout);
|
||||
.GetInitialInstanceProperties(*this);
|
||||
|
||||
std::map<gd::String, gd::PropertyDescriptor> nothing;
|
||||
return nothing;
|
||||
}
|
||||
|
||||
bool InitialInstance::UpdateCustomProperty(const gd::String& name,
|
||||
const gd::String& value,
|
||||
gd::Project& project,
|
||||
gd::Layout& layout) {
|
||||
if (layout.HasObjectNamed(GetObjectName()))
|
||||
return layout.GetObject(GetObjectName())
|
||||
bool InitialInstance::UpdateCustomProperty(
|
||||
const gd::String &name, const gd::String &value,
|
||||
gd::ObjectsContainer &globalObjectsContainer,
|
||||
gd::ObjectsContainer &objectsContainer) {
|
||||
if (objectsContainer.HasObjectNamed(GetObjectName()))
|
||||
return objectsContainer.GetObject(GetObjectName())
|
||||
.GetConfiguration()
|
||||
.UpdateInitialInstanceProperty(*this, name, value, project, layout);
|
||||
else if (project.HasObjectNamed(GetObjectName()))
|
||||
return project.GetObject(GetObjectName())
|
||||
.UpdateInitialInstanceProperty(*this, name, value);
|
||||
else if (globalObjectsContainer.HasObjectNamed(GetObjectName()))
|
||||
return globalObjectsContainer.GetObject(GetObjectName())
|
||||
.GetConfiguration()
|
||||
.UpdateInitialInstanceProperty(*this, name, value, project, layout);
|
||||
.UpdateInitialInstanceProperty(*this, name, value);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@@ -4,8 +4,8 @@
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef GDCORE_INITIALINSTANCE_H
|
||||
#define GDCORE_INITIALINSTANCE_H
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "GDCore/Project/VariablesContainer.h"
|
||||
@@ -14,6 +14,7 @@ namespace gd {
|
||||
class PropertyDescriptor;
|
||||
class Project;
|
||||
class Layout;
|
||||
class ObjectsContainer;
|
||||
} // namespace gd
|
||||
|
||||
namespace gd {
|
||||
@@ -263,18 +264,18 @@ class GD_CORE_API InitialInstance {
|
||||
* \note Common properties ( name, position... ) do not need to be
|
||||
* inserted in this map
|
||||
*/
|
||||
std::map<gd::String, gd::PropertyDescriptor> GetCustomProperties(
|
||||
gd::Project& project, gd::Layout& layout);
|
||||
std::map<gd::String, gd::PropertyDescriptor>
|
||||
GetCustomProperties(gd::ObjectsContainer &globalObjectsContainer,
|
||||
gd::ObjectsContainer &objectsContainer);
|
||||
|
||||
/**
|
||||
* \brief Update the property called \a name with the new \a value.
|
||||
*
|
||||
* \return false if the property could not be updated.
|
||||
*/
|
||||
bool UpdateCustomProperty(const gd::String& name,
|
||||
const gd::String& value,
|
||||
gd::Project& project,
|
||||
gd::Layout& layout);
|
||||
bool UpdateCustomProperty(const gd::String &name, const gd::String &value,
|
||||
gd::ObjectsContainer &globalObjectsContainer,
|
||||
gd::ObjectsContainer &objectsContainer);
|
||||
|
||||
/**
|
||||
* \brief Get the value of a double property stored in the instance.
|
||||
@@ -361,5 +362,3 @@ class GD_CORE_API InitialInstance {
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
||||
#endif // GDCORE_INITIALINSTANCE_H
|
||||
|
@@ -294,17 +294,6 @@ class GD_CORE_API Layer {
|
||||
static gd::Camera badCamera;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Functor testing layer name
|
||||
*
|
||||
* \see gd::Layer
|
||||
*/
|
||||
struct LayerHasName : public std::binary_function<gd::Layer, gd::String, bool> {
|
||||
bool operator()(const Layer& layer, const gd::String& name) const {
|
||||
return layer.GetName() == name;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
||||
#endif // GDCORE_LAYER_H
|
||||
|
138
Core/GDCore/Project/LayersContainer.cpp
Normal file
138
Core/GDCore/Project/LayersContainer.cpp
Normal file
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
|
||||
#include "LayersContainer.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
#include "Layer.h"
|
||||
#include "Layout.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace gd {
|
||||
|
||||
gd::Layer LayersContainer::badLayer;
|
||||
|
||||
LayersContainer::LayersContainer() {
|
||||
Reset();
|
||||
}
|
||||
|
||||
void LayersContainer::Reset() {
|
||||
layers.clear();
|
||||
gd::Layer layer;
|
||||
layer.SetCameraCount(1);
|
||||
layers.push_back(layer);
|
||||
}
|
||||
|
||||
gd::Layer& LayersContainer::GetLayer(const gd::String& name) {
|
||||
std::vector<gd::Layer>::iterator layer =
|
||||
find_if(layers.begin(), layers.end(), [&name](const gd::Layer& layer) {
|
||||
return layer.GetName() == name;
|
||||
});
|
||||
|
||||
if (layer != layers.end()) return *layer;
|
||||
|
||||
return badLayer;
|
||||
}
|
||||
|
||||
const gd::Layer& LayersContainer::GetLayer(const gd::String& name) const {
|
||||
std::vector<gd::Layer>::const_iterator layer =
|
||||
find_if(layers.begin(), layers.end(), [&name](const gd::Layer& layer) {
|
||||
return layer.GetName() == name;
|
||||
});
|
||||
|
||||
if (layer != layers.end()) return *layer;
|
||||
|
||||
return badLayer;
|
||||
}
|
||||
|
||||
gd::Layer& LayersContainer::GetLayer(std::size_t index) {
|
||||
return layers[index];
|
||||
}
|
||||
|
||||
const gd::Layer& LayersContainer::GetLayer(std::size_t index) const {
|
||||
return layers[index];
|
||||
}
|
||||
|
||||
std::size_t LayersContainer::GetLayersCount() const { return layers.size(); }
|
||||
|
||||
bool LayersContainer::HasLayerNamed(const gd::String& name) const {
|
||||
return (
|
||||
find_if(layers.begin(), layers.end(), [&name](const gd::Layer& layer) {
|
||||
return layer.GetName() == name;
|
||||
}) != layers.end());
|
||||
}
|
||||
std::size_t LayersContainer::GetLayerPosition(const gd::String& name) const {
|
||||
for (std::size_t i = 0; i < layers.size(); ++i) {
|
||||
if (layers[i].GetName() == name) return i;
|
||||
}
|
||||
return gd::String::npos;
|
||||
}
|
||||
|
||||
void LayersContainer::InsertNewLayer(const gd::String& name,
|
||||
std::size_t position) {
|
||||
gd::Layer newLayer;
|
||||
newLayer.SetName(name);
|
||||
if (position < layers.size())
|
||||
layers.insert(layers.begin() + position, newLayer);
|
||||
else
|
||||
layers.push_back(newLayer);
|
||||
}
|
||||
|
||||
void LayersContainer::InsertLayer(const gd::Layer& layer,
|
||||
std::size_t position) {
|
||||
if (position < layers.size())
|
||||
layers.insert(layers.begin() + position, layer);
|
||||
else
|
||||
layers.push_back(layer);
|
||||
}
|
||||
|
||||
void LayersContainer::RemoveLayer(const gd::String& name) {
|
||||
std::vector<gd::Layer>::iterator layer =
|
||||
find_if(layers.begin(), layers.end(), [&name](const gd::Layer& layer) {
|
||||
return layer.GetName() == name;
|
||||
});
|
||||
if (layer == layers.end()) return;
|
||||
|
||||
layers.erase(layer);
|
||||
}
|
||||
|
||||
void LayersContainer::SwapLayers(std::size_t firstLayerIndex,
|
||||
std::size_t secondLayerIndex) {
|
||||
if (firstLayerIndex >= layers.size() || secondLayerIndex >= layers.size())
|
||||
return;
|
||||
|
||||
std::iter_swap(layers.begin() + firstLayerIndex,
|
||||
layers.begin() + secondLayerIndex);
|
||||
}
|
||||
|
||||
void LayersContainer::MoveLayer(std::size_t oldIndex, std::size_t newIndex) {
|
||||
if (oldIndex >= layers.size() || newIndex >= layers.size()) return;
|
||||
|
||||
auto layer = layers[oldIndex];
|
||||
layers.erase(layers.begin() + oldIndex);
|
||||
InsertLayer(layer, newIndex);
|
||||
}
|
||||
|
||||
void LayersContainer::SerializeLayersTo(SerializerElement& element) const {
|
||||
element.ConsiderAsArrayOf("layer");
|
||||
for (std::size_t j = 0; j < GetLayersCount(); ++j)
|
||||
GetLayer(j).SerializeTo(element.AddChild("layer"));
|
||||
}
|
||||
|
||||
void LayersContainer::UnserializeLayersFrom(const SerializerElement& element) {
|
||||
layers.clear();
|
||||
element.ConsiderAsArrayOf("layer", "Layer");
|
||||
for (std::size_t i = 0; i < element.GetChildrenCount(); ++i) {
|
||||
gd::Layer layer;
|
||||
layer.UnserializeFrom(element.GetChild(i));
|
||||
layers.push_back(layer);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace gd
|
109
Core/GDCore/Project/LayersContainer.h
Normal file
109
Core/GDCore/Project/LayersContainer.h
Normal file
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* 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 <vector>
|
||||
|
||||
#include "GDCore/Project/Layer.h"
|
||||
#include "GDCore/String.h"
|
||||
|
||||
namespace gd {
|
||||
|
||||
/**
|
||||
* \brief Contains the layers for a scene or a custom object.
|
||||
*
|
||||
* \ingroup PlatformDefinition
|
||||
*/
|
||||
class GD_CORE_API LayersContainer {
|
||||
public:
|
||||
LayersContainer();
|
||||
|
||||
/**
|
||||
* \brief Return true if the layer called "name" exists.
|
||||
*/
|
||||
bool HasLayerNamed(const gd::String& name) const;
|
||||
|
||||
/**
|
||||
* \brief Return a reference to the layer called "name".
|
||||
*/
|
||||
Layer& GetLayer(const gd::String& name);
|
||||
|
||||
/**
|
||||
* \brief Return a reference to the layer called "name".
|
||||
*/
|
||||
const Layer& GetLayer(const gd::String& name) const;
|
||||
|
||||
/**
|
||||
* \brief Return a reference to the layer at position "index" in the layers
|
||||
* list.
|
||||
*/
|
||||
Layer& GetLayer(std::size_t index);
|
||||
|
||||
/**
|
||||
* \brief Return a reference to the layer at position "index" in the layers
|
||||
* list.
|
||||
*/
|
||||
const Layer& GetLayer(std::size_t index) const;
|
||||
|
||||
/**
|
||||
* \brief Return the position of the layer called "name" in the layers list.
|
||||
*/
|
||||
std::size_t GetLayerPosition(const gd::String& name) const;
|
||||
|
||||
/**
|
||||
* The number of layers.
|
||||
*/
|
||||
std::size_t GetLayersCount() const;
|
||||
|
||||
/**
|
||||
* Add a new empty the layer sheet called "name" at the specified
|
||||
* position in the layers list.
|
||||
*/
|
||||
void InsertNewLayer(const gd::String& name, std::size_t position);
|
||||
|
||||
/**
|
||||
* Add a new layer constructed from the layer passed as parameter.
|
||||
*
|
||||
* \param theLayer The layer that must be copied and inserted.
|
||||
* \param position Insertion position.
|
||||
*/
|
||||
void InsertLayer(const Layer& theLayer, std::size_t position);
|
||||
|
||||
/**
|
||||
* Delete the layer named "name".
|
||||
*/
|
||||
void RemoveLayer(const gd::String& name);
|
||||
|
||||
/**
|
||||
* Swap the position of the specified layers.
|
||||
*/
|
||||
void SwapLayers(std::size_t firstLayerIndex, std::size_t secondLayerIndex);
|
||||
|
||||
/**
|
||||
* Change the position of the specified layer.
|
||||
*/
|
||||
void MoveLayer(std::size_t oldIndex, std::size_t newIndex);
|
||||
|
||||
void Reset();
|
||||
|
||||
/**
|
||||
* \brief Serialize the layers.
|
||||
*/
|
||||
void SerializeLayersTo(SerializerElement& element) const;
|
||||
|
||||
/**
|
||||
* \brief Unserialize the layers.
|
||||
*/
|
||||
void UnserializeLayersFrom(const SerializerElement& element);
|
||||
|
||||
private:
|
||||
static gd::Layer badLayer; ///< Null object, returned when GetLayer can not
|
||||
///< find an appropriate layer.
|
||||
std::vector<gd::Layer> layers; ///< Layers
|
||||
};
|
||||
|
||||
} // namespace gd
|
@@ -33,7 +33,6 @@ using namespace std;
|
||||
|
||||
namespace gd {
|
||||
|
||||
gd::Layer Layout::badLayer;
|
||||
gd::BehaviorsSharedData Layout::badBehaviorSharedData("", "");
|
||||
|
||||
Layout::Layout(const Layout& other) { Init(other); }
|
||||
@@ -53,12 +52,8 @@ Layout::Layout()
|
||||
stopSoundsOnStartup(true),
|
||||
standardSortMethod(true),
|
||||
disableInputWhenNotFocused(true),
|
||||
profiler(NULL),
|
||||
variables(gd::VariablesContainer::SourceType::Scene)
|
||||
{
|
||||
gd::Layer layer;
|
||||
layer.SetCameraCount(1);
|
||||
initialLayers.push_back(layer);
|
||||
}
|
||||
|
||||
void Layout::SetName(const gd::String& name_) {
|
||||
@@ -100,91 +95,47 @@ Layout::GetAllBehaviorSharedData() const {
|
||||
}
|
||||
|
||||
gd::Layer& Layout::GetLayer(const gd::String& name) {
|
||||
std::vector<gd::Layer>::iterator layer =
|
||||
find_if(initialLayers.begin(),
|
||||
initialLayers.end(),
|
||||
bind2nd(gd::LayerHasName(), name));
|
||||
|
||||
if (layer != initialLayers.end()) return *layer;
|
||||
|
||||
return badLayer;
|
||||
return layers.GetLayer(name);
|
||||
}
|
||||
|
||||
const gd::Layer& Layout::GetLayer(const gd::String& name) const {
|
||||
std::vector<gd::Layer>::const_iterator layer =
|
||||
find_if(initialLayers.begin(),
|
||||
initialLayers.end(),
|
||||
bind2nd(gd::LayerHasName(), name));
|
||||
|
||||
if (layer != initialLayers.end()) return *layer;
|
||||
|
||||
return badLayer;
|
||||
return layers.GetLayer(name);
|
||||
}
|
||||
|
||||
gd::Layer& Layout::GetLayer(std::size_t index) { return initialLayers[index]; }
|
||||
gd::Layer& Layout::GetLayer(std::size_t index) { return layers.GetLayer(index); }
|
||||
|
||||
const gd::Layer& Layout::GetLayer(std::size_t index) const {
|
||||
return initialLayers[index];
|
||||
return layers.GetLayer(index);
|
||||
}
|
||||
|
||||
std::size_t Layout::GetLayersCount() const { return initialLayers.size(); }
|
||||
std::size_t Layout::GetLayersCount() const { return layers.GetLayersCount(); }
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
bool Layout::HasLayerNamed(const gd::String& name) const {
|
||||
return (find_if(initialLayers.begin(),
|
||||
initialLayers.end(),
|
||||
bind2nd(gd::LayerHasName(), name)) != initialLayers.end());
|
||||
return layers.HasLayerNamed(name);
|
||||
}
|
||||
std::size_t Layout::GetLayerPosition(const gd::String& name) const {
|
||||
for (std::size_t i = 0; i < initialLayers.size(); ++i) {
|
||||
if (initialLayers[i].GetName() == name) return i;
|
||||
}
|
||||
return gd::String::npos;
|
||||
return layers.GetLayerPosition(name);
|
||||
}
|
||||
|
||||
void Layout::InsertNewLayer(const gd::String& name, std::size_t position) {
|
||||
gd::Layer newLayer;
|
||||
newLayer.SetName(name);
|
||||
if (position < initialLayers.size())
|
||||
initialLayers.insert(initialLayers.begin() + position, newLayer);
|
||||
else
|
||||
initialLayers.push_back(newLayer);
|
||||
layers.InsertNewLayer(name, position);
|
||||
}
|
||||
|
||||
void Layout::InsertLayer(const gd::Layer& layer, std::size_t position) {
|
||||
if (position < initialLayers.size())
|
||||
initialLayers.insert(initialLayers.begin() + position, layer);
|
||||
else
|
||||
initialLayers.push_back(layer);
|
||||
layers.InsertLayer(layer, position);
|
||||
}
|
||||
|
||||
void Layout::RemoveLayer(const gd::String& name) {
|
||||
std::vector<gd::Layer>::iterator layer =
|
||||
find_if(initialLayers.begin(),
|
||||
initialLayers.end(),
|
||||
bind2nd(gd::LayerHasName(), name));
|
||||
if (layer == initialLayers.end()) return;
|
||||
|
||||
initialLayers.erase(layer);
|
||||
layers.RemoveLayer(name);
|
||||
}
|
||||
|
||||
void Layout::SwapLayers(std::size_t firstLayerIndex,
|
||||
std::size_t secondLayerIndex) {
|
||||
if (firstLayerIndex >= initialLayers.size() ||
|
||||
secondLayerIndex >= initialLayers.size())
|
||||
return;
|
||||
|
||||
std::iter_swap(initialLayers.begin() + firstLayerIndex,
|
||||
initialLayers.begin() + secondLayerIndex);
|
||||
layers.SwapLayers(firstLayerIndex, secondLayerIndex);
|
||||
}
|
||||
|
||||
void Layout::MoveLayer(std::size_t oldIndex, std::size_t newIndex) {
|
||||
if (oldIndex >= initialLayers.size() || newIndex >= initialLayers.size())
|
||||
return;
|
||||
|
||||
auto layer = initialLayers[oldIndex];
|
||||
initialLayers.erase(initialLayers.begin() + oldIndex);
|
||||
InsertLayer(layer, newIndex);
|
||||
layers.MoveLayer(oldIndex, newIndex);
|
||||
}
|
||||
|
||||
void Layout::UpdateBehaviorsSharedData(gd::Project& project) {
|
||||
@@ -192,22 +143,23 @@ void Layout::UpdateBehaviorsSharedData(gd::Project& project) {
|
||||
std::vector<gd::String> allBehaviorsNames;
|
||||
|
||||
// Search in objects for the type and the name of every behaviors.
|
||||
for (std::size_t i = 0; i < initialObjects.size(); ++i) {
|
||||
for (std::size_t i = 0; i < objectsContainer.GetObjectsCount(); ++i) {
|
||||
std::vector<gd::String> objectBehaviors =
|
||||
initialObjects[i]->GetAllBehaviorNames();
|
||||
objectsContainer.GetObject(i).GetAllBehaviorNames();
|
||||
for (unsigned int j = 0; j < objectBehaviors.size(); ++j) {
|
||||
auto& behavior =
|
||||
initialObjects[i]->GetBehavior(objectBehaviors[j]);
|
||||
objectsContainer.GetObject(i).GetBehavior(objectBehaviors[j]);
|
||||
allBehaviorsTypes.push_back(behavior.GetTypeName());
|
||||
allBehaviorsNames.push_back(behavior.GetName());
|
||||
}
|
||||
}
|
||||
for (std::size_t i = 0; i < project.GetObjectsCount(); ++i) {
|
||||
auto &globalObjects = project.GetObjects();
|
||||
for (std::size_t i = 0; i < globalObjects.GetObjectsCount(); ++i) {
|
||||
std::vector<gd::String> objectBehaviors =
|
||||
project.GetObject(i).GetAllBehaviorNames();
|
||||
globalObjects.GetObject(i).GetAllBehaviorNames();
|
||||
for (std::size_t j = 0; j < objectBehaviors.size(); ++j) {
|
||||
auto& behavior =
|
||||
project.GetObject(i).GetBehavior(objectBehaviors[j]);
|
||||
globalObjects.GetObject(i).GetBehavior(objectBehaviors[j]);
|
||||
allBehaviorsTypes.push_back(behavior.GetTypeName());
|
||||
allBehaviorsNames.push_back(behavior.GetName());
|
||||
}
|
||||
@@ -291,15 +243,15 @@ void Layout::SerializeTo(SerializerElement& element) const {
|
||||
|
||||
editorSettings.SerializeTo(element.AddChild("uiSettings"));
|
||||
|
||||
GetObjectGroups().SerializeTo(element.AddChild("objectsGroups"));
|
||||
objectsContainer.GetObjectGroups().SerializeTo(element.AddChild("objectsGroups"));
|
||||
GetVariables().SerializeTo(element.AddChild("variables"));
|
||||
GetInitialInstances().SerializeTo(element.AddChild("instances"));
|
||||
SerializeObjectsTo(element.AddChild("objects"));
|
||||
SerializeFoldersTo(element.AddChild("objectsFolderStructure"));
|
||||
objectsContainer.SerializeObjectsTo(element.AddChild("objects"));
|
||||
objectsContainer.SerializeFoldersTo(element.AddChild("objectsFolderStructure"));
|
||||
gd::EventsListSerialization::SerializeEventsTo(events,
|
||||
element.AddChild("events"));
|
||||
|
||||
SerializeLayersTo(element.AddChild("layers"));
|
||||
layers.SerializeLayersTo(element.AddChild("layers"));
|
||||
|
||||
SerializerElement& behaviorDatasElement =
|
||||
element.AddChild("behaviorsSharedData");
|
||||
@@ -317,23 +269,6 @@ void Layout::SerializeTo(SerializerElement& element) const {
|
||||
}
|
||||
}
|
||||
|
||||
void Layout::SerializeLayersTo(SerializerElement& element) const {
|
||||
element.ConsiderAsArrayOf("layer");
|
||||
for (std::size_t j = 0; j < GetLayersCount(); ++j)
|
||||
GetLayer(j).SerializeTo(element.AddChild("layer"));
|
||||
}
|
||||
#endif
|
||||
|
||||
void Layout::UnserializeLayersFrom(const SerializerElement& element) {
|
||||
initialLayers.clear();
|
||||
element.ConsiderAsArrayOf("layer", "Layer");
|
||||
for (std::size_t i = 0; i < element.GetChildrenCount(); ++i) {
|
||||
gd::Layer layer;
|
||||
layer.UnserializeFrom(element.GetChild(i));
|
||||
initialLayers.push_back(layer);
|
||||
}
|
||||
}
|
||||
|
||||
void Layout::UnserializeFrom(gd::Project& project,
|
||||
const SerializerElement& element) {
|
||||
SetBackgroundColor(element.GetIntAttribute("r"),
|
||||
@@ -349,22 +284,22 @@ void Layout::UnserializeFrom(gd::Project& project,
|
||||
editorSettings.UnserializeFrom(
|
||||
element.GetChild("uiSettings", 0, "UISettings"));
|
||||
|
||||
GetObjectGroups().UnserializeFrom(
|
||||
objectsContainer.GetObjectGroups().UnserializeFrom(
|
||||
element.GetChild("objectsGroups", 0, "GroupesObjets"));
|
||||
gd::EventsListSerialization::UnserializeEventsFrom(
|
||||
project, GetEvents(), element.GetChild("events", 0, "Events"));
|
||||
|
||||
UnserializeObjectsFrom(project, element.GetChild("objects", 0, "Objets"));
|
||||
objectsContainer.UnserializeObjectsFrom(project, element.GetChild("objects", 0, "Objets"));
|
||||
if (element.HasChild("objectsFolderStructure")) {
|
||||
UnserializeFoldersFrom(project, element.GetChild("objectsFolderStructure", 0));
|
||||
objectsContainer.UnserializeFoldersFrom(project, element.GetChild("objectsFolderStructure", 0));
|
||||
}
|
||||
AddMissingObjectsInRootFolder();
|
||||
objectsContainer.AddMissingObjectsInRootFolder();
|
||||
|
||||
initialInstances.UnserializeFrom(
|
||||
element.GetChild("instances", 0, "Positions"));
|
||||
variables.UnserializeFrom(element.GetChild("variables", 0, "Variables"));
|
||||
|
||||
UnserializeLayersFrom(element.GetChild("layers", 0, "Layers"));
|
||||
layers.UnserializeLayersFrom(element.GetChild("layers", 0, "Layers"));
|
||||
|
||||
// Compatibility with GD <= 4
|
||||
gd::String deprecatedTag1 = "automatismsSharedData";
|
||||
@@ -416,10 +351,10 @@ void Layout::Init(const Layout& other) {
|
||||
stopSoundsOnStartup = other.stopSoundsOnStartup;
|
||||
disableInputWhenNotFocused = other.disableInputWhenNotFocused;
|
||||
initialInstances = other.initialInstances;
|
||||
initialLayers = other.initialLayers;
|
||||
layers = other.layers;
|
||||
variables = other.GetVariables();
|
||||
|
||||
initialObjects = gd::Clone(other.initialObjects);
|
||||
objectsContainer = other.objectsContainer;
|
||||
|
||||
behaviorsSharedData.clear();
|
||||
for (const auto& it : other.behaviorsSharedData) {
|
||||
@@ -429,9 +364,6 @@ void Layout::Init(const Layout& other) {
|
||||
|
||||
events = other.events;
|
||||
editorSettings = other.editorSettings;
|
||||
objectGroups = other.objectGroups;
|
||||
|
||||
profiler = other.profiler;
|
||||
}
|
||||
|
||||
std::vector<gd::String> GetHiddenLayers(const Layout& layout) {
|
||||
|
@@ -9,15 +9,17 @@
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "GDCore/Events/EventsList.h"
|
||||
#include "GDCore/IDE/Dialogs/LayoutEditorCanvas/EditorSettings.h"
|
||||
#include "GDCore/Project/BehaviorsSharedData.h"
|
||||
#include "GDCore/Project/InitialInstancesContainer.h"
|
||||
#include "GDCore/Project/Layer.h"
|
||||
#include "GDCore/Project/LayersContainer.h"
|
||||
#include "GDCore/Project/ObjectGroupsContainer.h"
|
||||
#include "GDCore/Project/ObjectsContainer.h"
|
||||
#include "GDCore/Project/VariablesContainer.h"
|
||||
#include "GDCore/String.h"
|
||||
#include "GDCore/IDE/Dialogs/LayoutEditorCanvas/EditorSettings.h"
|
||||
|
||||
namespace gd {
|
||||
class BaseEvent;
|
||||
@@ -25,7 +27,6 @@ class Object;
|
||||
class Project;
|
||||
class InitialInstancesContainer;
|
||||
} // namespace gd
|
||||
class TiXmlElement;
|
||||
class BaseProfiler;
|
||||
#undef GetObject // Disable an annoying macro
|
||||
|
||||
@@ -36,7 +37,7 @@ namespace gd {
|
||||
*
|
||||
* \ingroup PlatformDefinition
|
||||
*/
|
||||
class GD_CORE_API Layout : public ObjectsContainer {
|
||||
class GD_CORE_API Layout {
|
||||
public:
|
||||
Layout();
|
||||
Layout(const Layout&);
|
||||
@@ -104,6 +105,24 @@ class GD_CORE_API Layout : public ObjectsContainer {
|
||||
|
||||
///@}
|
||||
|
||||
/** \name Layout's objects
|
||||
*/
|
||||
///@{
|
||||
/**
|
||||
* \brief return the objects of the scene.
|
||||
*/
|
||||
gd::ObjectsContainer& GetObjects() {
|
||||
return objectsContainer;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return the objects of the scene.
|
||||
*/
|
||||
const gd::ObjectsContainer& GetObjects() const {
|
||||
return objectsContainer;
|
||||
}
|
||||
///@}
|
||||
|
||||
/** \name Layout's initial instances
|
||||
* Members functions related to initial instances of objects created at the
|
||||
* layout start up
|
||||
@@ -147,103 +166,96 @@ class GD_CORE_API Layout : public ObjectsContainer {
|
||||
///@{
|
||||
|
||||
/**
|
||||
* Provide access to the gd::VariablesContainer member containing the layout
|
||||
* variables \see gd::VariablesContainer
|
||||
* \brief Get the variables of the scene.
|
||||
*
|
||||
* \see gd::VariablesContainer
|
||||
*/
|
||||
inline const gd::VariablesContainer& GetVariables() const {
|
||||
return variables;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide access to the gd::VariablesContainer member containing the layout
|
||||
* variables \see gd::VariablesContainer
|
||||
* \brief Get the variables of the scene.
|
||||
*
|
||||
* \see gd::VariablesContainer
|
||||
*/
|
||||
inline gd::VariablesContainer& GetVariables() { return variables; }
|
||||
|
||||
///@}
|
||||
|
||||
/** \name Layout layers management
|
||||
* Members functions related to layout layers management.
|
||||
* TODO: This could be moved to a separate class
|
||||
/** \name Layers
|
||||
*/
|
||||
///@{
|
||||
|
||||
/**
|
||||
* \brief Return true if the layer called "name" exists.
|
||||
* \brief Get the layers of the scene.
|
||||
*/
|
||||
const gd::LayersContainer& GetLayers() const { return layers; }
|
||||
|
||||
/**
|
||||
* \brief Get the layers of the scene.
|
||||
*/
|
||||
gd::LayersContainer& GetLayers() { return layers; }
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
bool HasLayerNamed(const gd::String& name) const;
|
||||
|
||||
/**
|
||||
* \brief Return a reference to the layer called "name".
|
||||
* @deprecated
|
||||
*/
|
||||
Layer& GetLayer(const gd::String& name);
|
||||
|
||||
/**
|
||||
* \brief Return a reference to the layer called "name".
|
||||
* @deprecated
|
||||
*/
|
||||
const Layer& GetLayer(const gd::String& name) const;
|
||||
|
||||
/**
|
||||
* \brief Return a reference to the layer at position "index" in the layers
|
||||
* list
|
||||
* @deprecated
|
||||
*/
|
||||
Layer& GetLayer(std::size_t index);
|
||||
|
||||
/**
|
||||
* \brief Return a reference to the layer at position "index" in the layers
|
||||
* list
|
||||
* @deprecated
|
||||
*/
|
||||
const Layer& GetLayer(std::size_t index) const;
|
||||
|
||||
/**
|
||||
* \brief Return the position of the layer called "name" in the layers list
|
||||
* @deprecated
|
||||
*/
|
||||
std::size_t GetLayerPosition(const gd::String& name) const;
|
||||
|
||||
/**
|
||||
* Must return the number of layers.
|
||||
* @deprecated
|
||||
*/
|
||||
std::size_t GetLayersCount() const;
|
||||
|
||||
/**
|
||||
* Must add a new empty the layer sheet called "name" at the specified
|
||||
* position in the layout list.
|
||||
* @deprecated
|
||||
*/
|
||||
void InsertNewLayer(const gd::String& name, std::size_t position);
|
||||
|
||||
/**
|
||||
* Must add a new the layer constructed from the layout passed as parameter.
|
||||
* \note No pointer or reference must be kept on the layer passed as
|
||||
* parameter. \param theLayer the layer that must be copied and inserted
|
||||
* into the project \param position Insertion position. Even if the position
|
||||
* is invalid, the layer must be inserted at the end of the layers list.
|
||||
* @deprecated
|
||||
*/
|
||||
void InsertLayer(const Layer& theLayer, std::size_t position);
|
||||
|
||||
/**
|
||||
* Must delete the layer named "name".
|
||||
* @deprecated
|
||||
*/
|
||||
void RemoveLayer(const gd::String& name);
|
||||
|
||||
/**
|
||||
* Swap the position of the specified layers.
|
||||
* @deprecated
|
||||
*/
|
||||
void SwapLayers(std::size_t firstLayerIndex, std::size_t secondLayerIndex);
|
||||
|
||||
/**
|
||||
* Change the position of the specified layer.
|
||||
* @deprecated
|
||||
*/
|
||||
void MoveLayer(std::size_t oldIndex, std::size_t newIndex);
|
||||
|
||||
/**
|
||||
* \brief Serialize the layers.
|
||||
*/
|
||||
void SerializeLayersTo(SerializerElement& element) const;
|
||||
|
||||
/**
|
||||
* \brief Unserialize the layers.
|
||||
*/
|
||||
void UnserializeLayersFrom(const SerializerElement& element);
|
||||
///@}
|
||||
|
||||
/**
|
||||
@@ -275,7 +287,8 @@ class GD_CORE_API Layout : public ObjectsContainer {
|
||||
/**
|
||||
* \brief Get the shared data stored for a behavior
|
||||
*/
|
||||
gd::BehaviorsSharedData& GetBehaviorSharedData(const gd::String& behaviorName);
|
||||
gd::BehaviorsSharedData& GetBehaviorSharedData(
|
||||
const gd::String& behaviorName);
|
||||
|
||||
/**
|
||||
* \brief Get a map of all shared data stored for behaviors
|
||||
@@ -283,7 +296,6 @@ class GD_CORE_API Layout : public ObjectsContainer {
|
||||
const std::map<gd::String, std::unique_ptr<gd::BehaviorsSharedData>>&
|
||||
GetAllBehaviorSharedData() const;
|
||||
|
||||
|
||||
/**
|
||||
* Return the settings associated to the layout.
|
||||
* \see gd::EditorSettings
|
||||
@@ -296,9 +308,7 @@ class GD_CORE_API Layout : public ObjectsContainer {
|
||||
* Return the settings associated to the layout.
|
||||
* \see gd::EditorSettings
|
||||
*/
|
||||
gd::EditorSettings& GetAssociatedEditorSettings() {
|
||||
return editorSettings;
|
||||
}
|
||||
gd::EditorSettings& GetAssociatedEditorSettings() { return editorSettings; }
|
||||
|
||||
/** \name Other properties
|
||||
*/
|
||||
@@ -339,12 +349,12 @@ class GD_CORE_API Layout : public ObjectsContainer {
|
||||
* launched
|
||||
*/
|
||||
bool StopSoundsOnStartup() const { return stopSoundsOnStartup; }
|
||||
///@}
|
||||
///@}
|
||||
|
||||
/** \name Saving and loading
|
||||
* Members functions related to saving and loading the object.
|
||||
*/
|
||||
///@{
|
||||
/** \name Saving and loading
|
||||
* Members functions related to saving and loading the object.
|
||||
*/
|
||||
///@{
|
||||
/**
|
||||
* \brief Serialize the layout.
|
||||
*/
|
||||
@@ -354,18 +364,7 @@ class GD_CORE_API Layout : public ObjectsContainer {
|
||||
* \brief Unserialize the layout.
|
||||
*/
|
||||
void UnserializeFrom(gd::Project& project, const SerializerElement& element);
|
||||
///@}
|
||||
|
||||
// TODO: GD C++ Platform specific code below
|
||||
/**
|
||||
* Get the profiler associated with the scene. Can be NULL.
|
||||
*/
|
||||
BaseProfiler* GetProfiler() const { return profiler; };
|
||||
|
||||
/**
|
||||
* Set the profiler associated with the scene. Can be NULL.
|
||||
*/
|
||||
void SetProfiler(BaseProfiler* profiler_) { profiler = profiler_; };
|
||||
///@}
|
||||
|
||||
private:
|
||||
gd::String name; ///< Scene name
|
||||
@@ -375,8 +374,9 @@ class GD_CORE_API Layout : public ObjectsContainer {
|
||||
unsigned int backgroundColorB; ///< Background color Blue component
|
||||
gd::String title; ///< Title displayed in the window
|
||||
gd::VariablesContainer variables; ///< Variables list
|
||||
gd::ObjectsContainer objectsContainer;
|
||||
gd::InitialInstancesContainer initialInstances; ///< Initial instances
|
||||
std::vector<gd::Layer> initialLayers; ///< Initial layers
|
||||
gd::LayersContainer layers;
|
||||
std::map<gd::String, std::unique_ptr<gd::BehaviorsSharedData>>
|
||||
behaviorsSharedData; ///< Initial shared datas of behaviors
|
||||
bool stopSoundsOnStartup; ///< True to make the scene stop all sounds at
|
||||
@@ -385,20 +385,14 @@ class GD_CORE_API Layout : public ObjectsContainer {
|
||||
bool disableInputWhenNotFocused; /// If set to true, the input must be
|
||||
/// disabled when the window do not have the
|
||||
/// focus.
|
||||
static gd::Layer badLayer; ///< Null object, returned when GetLayer can not
|
||||
///< find an appropriate layer.
|
||||
static gd::BehaviorsSharedData
|
||||
badBehaviorSharedData; ///< Null object, returned when
|
||||
///< GetBehaviorSharedData can not find the
|
||||
///< specified behavior shared data.
|
||||
///< GetBehaviorSharedData can not find the
|
||||
///< specified behavior shared data.
|
||||
|
||||
EventsList events; ///< Scene events
|
||||
gd::EditorSettings editorSettings;
|
||||
|
||||
// TODO: GD C++ Platform specific code below
|
||||
|
||||
BaseProfiler* profiler; ///< Pointer to the profiler. Can be NULL.
|
||||
|
||||
/**
|
||||
* Initialize from another layout. Used by copy-ctor and assign-op.
|
||||
* Don't forget to update me if members were changed!
|
||||
@@ -445,20 +439,24 @@ gd::String GD_CORE_API GetTypeOfObject(const ObjectsContainer& game,
|
||||
bool searchInGroups = true);
|
||||
/**
|
||||
* \brief Check if an object or all objects of a group has a behavior.
|
||||
* \deprecated Use gd::ObjectsContainersList::HasBehaviorInObjectOrGroup instead.
|
||||
* \deprecated Use gd::ObjectsContainersList::HasBehaviorInObjectOrGroup
|
||||
* instead.
|
||||
*/
|
||||
bool GD_CORE_API HasBehaviorInObjectOrGroup(const gd::ObjectsContainer &project,
|
||||
const gd::ObjectsContainer &layout,
|
||||
const gd::String &objectOrGroupName,
|
||||
const gd::String &behaviorName,
|
||||
bool GD_CORE_API HasBehaviorInObjectOrGroup(const gd::ObjectsContainer& project,
|
||||
const gd::ObjectsContainer& layout,
|
||||
const gd::String& objectOrGroupName,
|
||||
const gd::String& behaviorName,
|
||||
bool searchInGroups = true);
|
||||
/**
|
||||
* \brief Get the names of behavior of a given type if an object or all objects of a group has it.
|
||||
* \brief Get the names of behavior of a given type if an object or all objects
|
||||
* of a group has it.
|
||||
*/
|
||||
std::vector<gd::String> GD_CORE_API GetBehaviorNamesInObjectOrGroup(
|
||||
const gd::ObjectsContainer &project, const gd::ObjectsContainer &layout,
|
||||
const gd::String &objectOrGroupName, const gd::String &behaviorType,
|
||||
bool searchInGroups);
|
||||
std::vector<gd::String> GD_CORE_API
|
||||
GetBehaviorNamesInObjectOrGroup(const gd::ObjectsContainer& project,
|
||||
const gd::ObjectsContainer& layout,
|
||||
const gd::String& objectOrGroupName,
|
||||
const gd::String& behaviorType,
|
||||
bool searchInGroups);
|
||||
|
||||
/**
|
||||
* \brief Check if a behavior is a default one or doesn't exist in an object or
|
||||
@@ -471,13 +469,15 @@ bool GD_CORE_API IsDefaultBehavior(const gd::ObjectsContainer& project,
|
||||
bool searchInGroups = true);
|
||||
|
||||
/**
|
||||
* \brief Get the type of a behavior if an object or all objects of a group has it.
|
||||
* \brief Get the type of a behavior if an object or all objects of a group has
|
||||
* it.
|
||||
*/
|
||||
gd::String GD_CORE_API GetTypeOfBehaviorInObjectOrGroup(const gd::ObjectsContainer &project,
|
||||
const gd::ObjectsContainer &layout,
|
||||
const gd::String &objectOrGroupName,
|
||||
const gd::String &behaviorName,
|
||||
bool searchInGroups = true);
|
||||
gd::String GD_CORE_API
|
||||
GetTypeOfBehaviorInObjectOrGroup(const gd::ObjectsContainer& project,
|
||||
const gd::ObjectsContainer& layout,
|
||||
const gd::String& objectOrGroupName,
|
||||
const gd::String& behaviorName,
|
||||
bool searchInGroups = true);
|
||||
/**
|
||||
* \brief Get a type from a behavior name
|
||||
* @return Type of the behavior.
|
||||
|
@@ -25,9 +25,7 @@ std::map<gd::String, gd::PropertyDescriptor> ObjectConfiguration::GetProperties(
|
||||
}
|
||||
|
||||
std::map<gd::String, gd::PropertyDescriptor>
|
||||
ObjectConfiguration::GetInitialInstanceProperties(const gd::InitialInstance& instance,
|
||||
gd::Project& project,
|
||||
gd::Layout& layout) {
|
||||
ObjectConfiguration::GetInitialInstanceProperties(const gd::InitialInstance& instance) {
|
||||
std::map<gd::String, gd::PropertyDescriptor> nothing;
|
||||
return nothing;
|
||||
}
|
||||
|
@@ -114,9 +114,7 @@ class GD_CORE_API ObjectConfiguration {
|
||||
* \see gd::InitialInstance
|
||||
*/
|
||||
virtual std::map<gd::String, gd::PropertyDescriptor>
|
||||
GetInitialInstanceProperties(const gd::InitialInstance& instance,
|
||||
gd::Project& project,
|
||||
gd::Layout& layout);
|
||||
GetInitialInstanceProperties(const gd::InitialInstance& instance);
|
||||
|
||||
/**
|
||||
* \brief Called when the IDE wants to update a custom property of an initial
|
||||
@@ -127,9 +125,7 @@ class GD_CORE_API ObjectConfiguration {
|
||||
*/
|
||||
virtual bool UpdateInitialInstanceProperty(gd::InitialInstance& instance,
|
||||
const gd::String& name,
|
||||
const gd::String& value,
|
||||
gd::Project& project,
|
||||
gd::Layout& layout) {
|
||||
const gd::String& value) {
|
||||
return false;
|
||||
};
|
||||
///@}
|
||||
|
@@ -7,6 +7,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "GDCore/Tools/PolymorphicClone.h"
|
||||
#include "GDCore/Extensions/Platform.h"
|
||||
#include "GDCore/Project/Object.h"
|
||||
#include "GDCore/Project/ObjectFolderOrObject.h"
|
||||
@@ -21,6 +22,25 @@ ObjectsContainer::ObjectsContainer() {
|
||||
|
||||
ObjectsContainer::~ObjectsContainer() {}
|
||||
|
||||
ObjectsContainer::ObjectsContainer(const ObjectsContainer& other) {
|
||||
Init(other);
|
||||
}
|
||||
|
||||
ObjectsContainer& ObjectsContainer::operator=(
|
||||
const ObjectsContainer& other) {
|
||||
if (this != &other) Init(other);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void ObjectsContainer::Init(const gd::ObjectsContainer& other) {
|
||||
initialObjects = gd::Clone(other.initialObjects);
|
||||
objectGroups = other.objectGroups;
|
||||
// The objects folders are not copied.
|
||||
// It's not an issue because the UI uses the serialization for duplication.
|
||||
rootFolder = gd::make_unique<gd::ObjectFolderOrObject>("__ROOT");
|
||||
}
|
||||
|
||||
void ObjectsContainer::SerializeObjectsTo(SerializerElement& element) const {
|
||||
element.ConsiderAsArrayOf("object");
|
||||
for (std::size_t j = 0; j < initialObjects.size(); j++) {
|
||||
|
@@ -40,6 +40,9 @@ class GD_CORE_API ObjectsContainer {
|
||||
*/
|
||||
ObjectsContainer();
|
||||
virtual ~ObjectsContainer();
|
||||
|
||||
ObjectsContainer(const ObjectsContainer&);
|
||||
ObjectsContainer& operator=(const ObjectsContainer& rhs);
|
||||
|
||||
/** \name Objects management
|
||||
* Members functions related to objects management.
|
||||
@@ -230,6 +233,12 @@ class GD_CORE_API ObjectsContainer {
|
||||
|
||||
private:
|
||||
std::unique_ptr<gd::ObjectFolderOrObject> rootFolder;
|
||||
|
||||
/**
|
||||
* Initialize from another variables container, copying elements. Used by
|
||||
* copy-ctor and assign-op. Don't forget to update me if members were changed!
|
||||
*/
|
||||
void Init(const ObjectsContainer& other);
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -22,8 +22,8 @@ ObjectsContainersList
|
||||
ObjectsContainersList::MakeNewObjectsContainersListForProjectAndLayout(
|
||||
const gd::Project& project, const gd::Layout& layout) {
|
||||
ObjectsContainersList objectsContainersList;
|
||||
objectsContainersList.Add(project);
|
||||
objectsContainersList.Add(layout);
|
||||
objectsContainersList.Add(project.GetObjects());
|
||||
objectsContainersList.Add(layout.GetObjects());
|
||||
return objectsContainersList;
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ ObjectsContainersList
|
||||
ObjectsContainersList::MakeNewObjectsContainersListForProject(
|
||||
const gd::Project& project) {
|
||||
ObjectsContainersList objectsContainersList;
|
||||
objectsContainersList.Add(project);
|
||||
objectsContainersList.Add(project.GetObjects());
|
||||
return objectsContainersList;
|
||||
}
|
||||
|
||||
|
@@ -34,7 +34,6 @@
|
||||
#include "GDCore/Serialization/Serializer.h"
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
#include "GDCore/String.h"
|
||||
#include "GDCore/TinyXml/tinyxml.h"
|
||||
#include "GDCore/Tools/Localization.h"
|
||||
#include "GDCore/Tools/Log.h"
|
||||
#include "GDCore/Tools/PolymorphicClone.h"
|
||||
@@ -835,15 +834,15 @@ void Project::UnserializeFrom(const SerializerElement& element) {
|
||||
*this, eventsFunctionsExtensionElement);
|
||||
}
|
||||
|
||||
GetObjectGroups().UnserializeFrom(
|
||||
objectsContainer.GetObjectGroups().UnserializeFrom(
|
||||
element.GetChild("objectsGroups", 0, "ObjectGroups"));
|
||||
resourcesManager.UnserializeFrom(
|
||||
element.GetChild("resources", 0, "Resources"));
|
||||
UnserializeObjectsFrom(*this, element.GetChild("objects", 0, "Objects"));
|
||||
objectsContainer.UnserializeObjectsFrom(*this, element.GetChild("objects", 0, "Objects"));
|
||||
if (element.HasChild("objectsFolderStructure")) {
|
||||
UnserializeFoldersFrom(*this, element.GetChild("objectsFolderStructure", 0));
|
||||
objectsContainer.UnserializeFoldersFrom(*this, element.GetChild("objectsFolderStructure", 0));
|
||||
}
|
||||
AddMissingObjectsInRootFolder();
|
||||
objectsContainer.AddMissingObjectsInRootFolder();
|
||||
|
||||
GetVariables().UnserializeFrom(element.GetChild("variables", 0, "Variables"));
|
||||
|
||||
@@ -995,9 +994,9 @@ void Project::SerializeTo(SerializerElement& element) const {
|
||||
std::cout << "ERROR: The project current platform is NULL.";
|
||||
|
||||
resourcesManager.SerializeTo(element.AddChild("resources"));
|
||||
SerializeObjectsTo(element.AddChild("objects"));
|
||||
SerializeFoldersTo(element.AddChild("objectsFolderStructure"));
|
||||
GetObjectGroups().SerializeTo(element.AddChild("objectsGroups"));
|
||||
objectsContainer.SerializeObjectsTo(element.AddChild("objects"));
|
||||
objectsContainer.SerializeFoldersTo(element.AddChild("objectsFolderStructure"));
|
||||
objectsContainer.GetObjectGroups().SerializeTo(element.AddChild("objectsGroups"));
|
||||
GetVariables().SerializeTo(element.AddChild("variables"));
|
||||
|
||||
element.SetAttribute("firstLayout", firstLayout);
|
||||
@@ -1164,7 +1163,6 @@ void Project::Init(const gd::Project& game) {
|
||||
platformSpecificAssets = game.platformSpecificAssets;
|
||||
loadingScreen = game.loadingScreen;
|
||||
watermark = game.watermark;
|
||||
objectGroups = game.objectGroups;
|
||||
|
||||
extensionProperties = game.extensionProperties;
|
||||
|
||||
@@ -1177,7 +1175,7 @@ void Project::Init(const gd::Project& game) {
|
||||
|
||||
resourcesManager = game.resourcesManager;
|
||||
|
||||
initialObjects = gd::Clone(game.initialObjects);
|
||||
objectsContainer = game.objectsContainer;
|
||||
|
||||
scenes = gd::Clone(game.scenes);
|
||||
|
||||
|
@@ -48,7 +48,7 @@ namespace gd {
|
||||
*
|
||||
* \ingroup PlatformDefinition
|
||||
*/
|
||||
class GD_CORE_API Project : public ObjectsContainer {
|
||||
class GD_CORE_API Project {
|
||||
public:
|
||||
Project();
|
||||
Project(const Project&);
|
||||
@@ -984,6 +984,24 @@ class GD_CORE_API Project : public ObjectsContainer {
|
||||
|
||||
///@}
|
||||
|
||||
/** \name Global objects
|
||||
*/
|
||||
///@{
|
||||
/**
|
||||
* \brief return the objects of the project.
|
||||
*/
|
||||
gd::ObjectsContainer& GetObjects() {
|
||||
return objectsContainer;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return the objects of the project.
|
||||
*/
|
||||
const gd::ObjectsContainer& GetObjects() const {
|
||||
return objectsContainer;
|
||||
}
|
||||
///@}
|
||||
|
||||
/** \name Identifier names
|
||||
*/
|
||||
///@{
|
||||
@@ -1090,6 +1108,7 @@ class GD_CORE_API Project : public ObjectsContainer {
|
||||
///< startup.
|
||||
std::vector<std::unique_ptr<gd::Layout> > scenes; ///< List of all scenes
|
||||
gd::VariablesContainer variables; ///< Initial global variables
|
||||
gd::ObjectsContainer objectsContainer;
|
||||
std::vector<std::unique_ptr<gd::ExternalLayout> >
|
||||
externalLayouts; ///< List of all externals layouts
|
||||
std::vector<std::unique_ptr<gd::EventsFunctionsExtension> >
|
||||
|
@@ -6,6 +6,7 @@
|
||||
#include "GDCore/Project/EventsBasedObject.h"
|
||||
#include "GDCore/Project/ObjectsContainer.h"
|
||||
#include "GDCore/Events/Event.h"
|
||||
#include "GDCore/Extensions/PlatformExtension.h"
|
||||
|
||||
namespace gd {
|
||||
|
||||
@@ -101,6 +102,37 @@ ProjectScopedContainers::MakeNewProjectScopedContainersForObjectEventsFunction(
|
||||
return projectScopedContainers;
|
||||
}
|
||||
|
||||
ProjectScopedContainers
|
||||
ProjectScopedContainers::MakeNewProjectScopedContainersForEventsBasedObject(
|
||||
const gd::Project &project,
|
||||
const gd::EventsFunctionsExtension &eventsFunctionsExtension,
|
||||
const gd::EventsBasedObject &eventsBasedObject,
|
||||
gd::ObjectsContainer &outputObjectsContainer) {
|
||||
|
||||
outputObjectsContainer.GetObjects().clear();
|
||||
outputObjectsContainer.GetObjectGroups().Clear();
|
||||
outputObjectsContainer.InsertNewObject(
|
||||
project,
|
||||
gd::PlatformExtension::GetObjectFullType(
|
||||
eventsFunctionsExtension.GetName(), eventsBasedObject.GetName()),
|
||||
"Object", outputObjectsContainer.GetObjectsCount());
|
||||
gd::EventsFunctionTools::CopyEventsBasedObjectChildrenToObjectsContainer(
|
||||
eventsBasedObject, outputObjectsContainer);
|
||||
|
||||
ProjectScopedContainers projectScopedContainers(
|
||||
ObjectsContainersList::MakeNewObjectsContainersListForContainer(
|
||||
outputObjectsContainer),
|
||||
VariablesContainersList::
|
||||
MakeNewVariablesContainersListForEventsFunctionsExtension(
|
||||
eventsFunctionsExtension),
|
||||
PropertiesContainersList::MakeNewEmptyPropertiesContainersList());
|
||||
|
||||
projectScopedContainers.AddPropertiesContainer(
|
||||
eventsBasedObject.GetPropertyDescriptors());
|
||||
|
||||
return projectScopedContainers;
|
||||
}
|
||||
|
||||
ProjectScopedContainers
|
||||
ProjectScopedContainers::MakeNewProjectScopedContainersWithLocalVariables(
|
||||
const ProjectScopedContainers &projectScopedContainers,
|
||||
|
@@ -111,6 +111,13 @@ class ProjectScopedContainers {
|
||||
const gd::EventsFunction &eventsFunction,
|
||||
gd::ObjectsContainer ¶meterObjectsContainer);
|
||||
|
||||
static ProjectScopedContainers
|
||||
MakeNewProjectScopedContainersForEventsBasedObject(
|
||||
const gd::Project &project,
|
||||
const gd::EventsFunctionsExtension &eventsFunctionsExtension,
|
||||
const gd::EventsBasedObject &eventsBasedObject,
|
||||
gd::ObjectsContainer &outputObjectsContainer);
|
||||
|
||||
static ProjectScopedContainers
|
||||
MakeNewProjectScopedContainersWithLocalVariables(
|
||||
const ProjectScopedContainers &projectScopedContainers,
|
||||
|
@@ -11,7 +11,6 @@
|
||||
#include "GDCore/Project/Variable.h"
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
#include "GDCore/String.h"
|
||||
#include "GDCore/TinyXml/tinyxml.h"
|
||||
#include "GDCore/Tools/UUID/UUID.h"
|
||||
|
||||
namespace gd {
|
||||
|
@@ -12,7 +12,6 @@
|
||||
namespace gd {
|
||||
class SerializerElement;
|
||||
}
|
||||
class TiXmlElement;
|
||||
|
||||
namespace gd {
|
||||
|
||||
|
@@ -17,91 +17,11 @@
|
||||
#include "rapidjson/document.h"
|
||||
#include "rapidjson/prettywriter.h"
|
||||
#include "rapidjson/rapidjson.h"
|
||||
#if !defined(EMSCRIPTEN)
|
||||
#include "GDCore/TinyXml/tinyxml.h"
|
||||
#endif
|
||||
|
||||
using namespace rapidjson;
|
||||
|
||||
namespace gd {
|
||||
|
||||
#if !defined(EMSCRIPTEN)
|
||||
void Serializer::ToXML(SerializerElement& element, TiXmlElement* xmlElement) {
|
||||
if (!xmlElement) return;
|
||||
|
||||
if (element.IsValueUndefined()) {
|
||||
const std::map<gd::String, SerializerValue>& attributes =
|
||||
element.GetAllAttributes();
|
||||
for (std::map<gd::String, SerializerValue>::const_iterator it =
|
||||
attributes.begin();
|
||||
it != attributes.end();
|
||||
++it) {
|
||||
const SerializerValue& attr = it->second;
|
||||
|
||||
if (attr.IsBoolean())
|
||||
xmlElement->SetAttribute(it->first.c_str(),
|
||||
attr.GetBool() ? "true" : "false");
|
||||
else if (attr.IsString())
|
||||
xmlElement->SetAttribute(it->first.c_str(), attr.GetString().c_str());
|
||||
else if (attr.IsInt())
|
||||
xmlElement->SetAttribute(it->first.c_str(), attr.GetInt());
|
||||
else if (attr.IsDouble())
|
||||
xmlElement->SetDoubleAttribute(it->first.c_str(), attr.GetDouble());
|
||||
else
|
||||
xmlElement->SetAttribute(it->first.c_str(), attr.GetString().c_str());
|
||||
}
|
||||
|
||||
const std::vector<
|
||||
std::pair<gd::String, std::shared_ptr<SerializerElement> > >& children =
|
||||
element.GetAllChildren();
|
||||
for (size_t i = 0; i < children.size(); ++i) {
|
||||
if (children[i].second == std::shared_ptr<SerializerElement>()) continue;
|
||||
|
||||
TiXmlElement* xmlChild = new TiXmlElement(children[i].first.c_str());
|
||||
xmlElement->LinkEndChild(xmlChild);
|
||||
ToXML(*children[i].second, xmlChild);
|
||||
}
|
||||
} else {
|
||||
TiXmlText* xmlValue = new TiXmlText(element.GetValue().GetString().c_str());
|
||||
xmlElement->LinkEndChild(xmlValue);
|
||||
}
|
||||
}
|
||||
|
||||
void Serializer::FromXML(SerializerElement& element,
|
||||
const TiXmlElement* xmlElement) {
|
||||
if (!xmlElement) return;
|
||||
|
||||
const TiXmlAttribute* attr = xmlElement->FirstAttribute();
|
||||
while (attr) {
|
||||
if (attr->Name() != NULL) {
|
||||
gd::String name = gd::String::FromUTF8(attr->Name()).ReplaceInvalid();
|
||||
if (attr->Value())
|
||||
element.SetAttribute(
|
||||
name, gd::String::FromUTF8(attr->Value()).ReplaceInvalid());
|
||||
}
|
||||
|
||||
attr = attr->Next();
|
||||
}
|
||||
|
||||
const TiXmlElement* child = xmlElement->FirstChildElement();
|
||||
while (child) {
|
||||
if (child->Value()) {
|
||||
gd::String name = gd::String::FromUTF8(child->Value()).ReplaceInvalid();
|
||||
SerializerElement& childElement = element.AddChild(name);
|
||||
FromXML(childElement, child);
|
||||
}
|
||||
|
||||
child = child->NextSiblingElement();
|
||||
}
|
||||
|
||||
if (xmlElement->GetText()) {
|
||||
SerializerValue value;
|
||||
value.Set(gd::String::FromUTF8(xmlElement->GetText()).ReplaceInvalid());
|
||||
element.SetValue(value);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
gd::String Serializer::ToEscapedXMLString(const gd::String& str) {
|
||||
return str.FindAndReplace("&", "&")
|
||||
.FindAndReplace("'", "'")
|
||||
|
@@ -8,7 +8,6 @@
|
||||
#define GDCORE_SERIALIZER_H
|
||||
#include <string>
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
class TiXmlElement;
|
||||
|
||||
namespace gd {
|
||||
|
||||
@@ -22,11 +21,7 @@ class GD_CORE_API Serializer {
|
||||
* Convert a gd::SerializerElement from/to XML.
|
||||
*/
|
||||
///@{
|
||||
#if !defined(EMSCRIPTEN)
|
||||
static void ToXML(SerializerElement& element, TiXmlElement* xmlElement);
|
||||
static void FromXML(SerializerElement& element,
|
||||
const TiXmlElement* xmlElement);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Escape a string for inclusion in a XML tag
|
||||
*/
|
||||
|
@@ -1,117 +0,0 @@
|
||||
/*
|
||||
www.sourceforge.net/projects/tinyxml
|
||||
Original file by Yves Berquin.
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any
|
||||
damages arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any
|
||||
purpose, including commercial applications, and to alter it and
|
||||
redistribute it freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must
|
||||
not claim that you wrote the original software. If you use this
|
||||
software in a product, an acknowledgment in the product documentation
|
||||
would be appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and
|
||||
must not be misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
* THIS FILE WAS ALTERED BY Tyge L<>vset, 7. April 2005.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef TIXML_USE_STL
|
||||
|
||||
#include "GDCore/TinyXml/tinystr.h"
|
||||
|
||||
// Error value for find primitive
|
||||
const TiXmlString::size_type TiXmlString::npos = static_cast< TiXmlString::size_type >(-1);
|
||||
|
||||
|
||||
// Null rep.
|
||||
TiXmlString::Rep TiXmlString::nullrep_ = { 0, 0, { '\0' } };
|
||||
|
||||
|
||||
void TiXmlString::reserve (size_type cap)
|
||||
{
|
||||
if (cap > capacity())
|
||||
{
|
||||
TiXmlString tmp;
|
||||
tmp.init(length(), cap);
|
||||
memcpy(tmp.start(), data(), length());
|
||||
swap(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TiXmlString& TiXmlString::assign(const char* str, size_type len)
|
||||
{
|
||||
size_type cap = capacity();
|
||||
if (len > cap || cap > 3*(len + 8))
|
||||
{
|
||||
TiXmlString tmp;
|
||||
tmp.init(len);
|
||||
memcpy(tmp.start(), str, len);
|
||||
swap(tmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
memmove(start(), str, len);
|
||||
set_size(len);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
TiXmlString& TiXmlString::append(const char* str, size_type len)
|
||||
{
|
||||
size_type newsize = length() + len;
|
||||
if (newsize > capacity())
|
||||
{
|
||||
reserve (newsize + capacity());
|
||||
}
|
||||
memmove(finish(), str, len);
|
||||
set_size(newsize);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
TiXmlString operator + (const TiXmlString & a, const TiXmlString & b)
|
||||
{
|
||||
TiXmlString tmp;
|
||||
tmp.reserve(a.length() + b.length());
|
||||
tmp += a;
|
||||
tmp += b;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
TiXmlString operator + (const TiXmlString & a, const char* b)
|
||||
{
|
||||
TiXmlString tmp;
|
||||
TiXmlString::size_type b_len = static_cast<TiXmlString::size_type>( strlen(b) );
|
||||
tmp.reserve(a.length() + b_len);
|
||||
tmp += a;
|
||||
tmp.append(b, b_len);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
TiXmlString operator + (const char* a, const TiXmlString & b)
|
||||
{
|
||||
TiXmlString tmp;
|
||||
TiXmlString::size_type a_len = static_cast<TiXmlString::size_type>( strlen(a) );
|
||||
tmp.reserve(a_len + b.length());
|
||||
tmp.append(a, a_len);
|
||||
tmp += b;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
||||
#endif // TIXML_USE_STL
|
||||
|
@@ -1,325 +0,0 @@
|
||||
/*
|
||||
www.sourceforge.net/projects/tinyxml
|
||||
Original file by Yves Berquin.
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any
|
||||
damages arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any
|
||||
purpose, including commercial applications, and to alter it and
|
||||
redistribute it freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must
|
||||
not claim that you wrote the original software. If you use this
|
||||
software in a product, an acknowledgment in the product documentation
|
||||
would be appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and
|
||||
must not be misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
* THIS FILE WAS ALTERED BY Tyge Lovset, 7. April 2005.
|
||||
*
|
||||
* - completely rewritten. compact, clean, and fast implementation.
|
||||
* - sizeof(TiXmlString) = pointer size (4 bytes on 32-bit systems)
|
||||
* - fixed reserve() to work as per specification.
|
||||
* - fixed buggy compares operator==(), operator<(), and operator>()
|
||||
* - fixed operator+=() to take a const ref argument, following spec.
|
||||
* - added "copy" constructor with length, and most compare operators.
|
||||
* - added swap(), clear(), size(), capacity(), operator+().
|
||||
*/
|
||||
|
||||
/**
|
||||
* Changes by Florian Rival :
|
||||
* Added GD_CORE_API to integrate TinyXml to GDevelop Library.
|
||||
*/
|
||||
|
||||
#ifndef TIXML_USE_STL
|
||||
|
||||
#ifndef TIXML_STRING_INCLUDED
|
||||
#define TIXML_STRING_INCLUDED
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
/* The support for explicit isn't that universal, and it isn't really
|
||||
required - it is used to check that the TiXmlString class isn't incorrectly
|
||||
used. Be nice to old compilers and macro it here:
|
||||
*/
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200 )
|
||||
// Microsoft visual studio, version 6 and higher.
|
||||
#define TIXML_EXPLICIT explicit
|
||||
#elif defined(__GNUC__) && (__GNUC__ >= 3 )
|
||||
// GCC version 3 and higher.s
|
||||
#define TIXML_EXPLICIT explicit
|
||||
#else
|
||||
#define TIXML_EXPLICIT
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
TiXmlString is an emulation of a subset of the std::string template.
|
||||
Its purpose is to allow compiling TinyXML on compilers with no or poor STL support.
|
||||
Only the member functions relevant to the TinyXML project have been implemented.
|
||||
The buffer allocation is made by a simplistic power of 2 like mechanism : if we increase
|
||||
a string and there's no more room, we allocate a buffer twice as big as we need.
|
||||
*/
|
||||
class GD_CORE_API TiXmlString
|
||||
{
|
||||
public :
|
||||
// The size type used
|
||||
typedef size_t size_type;
|
||||
|
||||
// Error value for find primitive
|
||||
static const size_type npos; // = -1;
|
||||
|
||||
|
||||
// TiXmlString empty constructor
|
||||
TiXmlString () : rep_(&nullrep_)
|
||||
{
|
||||
}
|
||||
|
||||
// TiXmlString copy constructor
|
||||
TiXmlString ( const TiXmlString & copy) : rep_(0)
|
||||
{
|
||||
init(copy.length());
|
||||
memcpy(start(), copy.data(), length());
|
||||
}
|
||||
|
||||
// TiXmlString constructor, based on a string
|
||||
TIXML_EXPLICIT TiXmlString ( const char * copy) : rep_(0)
|
||||
{
|
||||
init( static_cast<size_type>( strlen(copy) ));
|
||||
memcpy(start(), copy, length());
|
||||
}
|
||||
|
||||
// TiXmlString constructor, based on a string
|
||||
TIXML_EXPLICIT TiXmlString ( const char * str, size_type len) : rep_(0)
|
||||
{
|
||||
init(len);
|
||||
memcpy(start(), str, len);
|
||||
}
|
||||
|
||||
// TiXmlString destructor
|
||||
~TiXmlString ()
|
||||
{
|
||||
quit();
|
||||
}
|
||||
|
||||
// = operator
|
||||
TiXmlString& operator = (const char * copy)
|
||||
{
|
||||
return assign( copy, (size_type)strlen(copy));
|
||||
}
|
||||
|
||||
// = operator
|
||||
TiXmlString& operator = (const TiXmlString & copy)
|
||||
{
|
||||
return assign(copy.start(), copy.length());
|
||||
}
|
||||
|
||||
|
||||
// += operator. Maps to append
|
||||
TiXmlString& operator += (const char * suffix)
|
||||
{
|
||||
return append(suffix, static_cast<size_type>( strlen(suffix) ));
|
||||
}
|
||||
|
||||
// += operator. Maps to append
|
||||
TiXmlString& operator += (char single)
|
||||
{
|
||||
return append(&single, 1);
|
||||
}
|
||||
|
||||
// += operator. Maps to append
|
||||
TiXmlString& operator += (const TiXmlString & suffix)
|
||||
{
|
||||
return append(suffix.data(), suffix.length());
|
||||
}
|
||||
|
||||
|
||||
// Convert a TiXmlString into a null-terminated char *
|
||||
const char * c_str () const { return rep_->str; }
|
||||
|
||||
// Convert a TiXmlString into a char * (need not be null terminated).
|
||||
const char * data () const { return rep_->str; }
|
||||
|
||||
// Return the length of a TiXmlString
|
||||
size_type length () const { return rep_->size; }
|
||||
|
||||
// Alias for length()
|
||||
size_type size () const { return rep_->size; }
|
||||
|
||||
// Checks if a TiXmlString is empty
|
||||
bool empty () const { return rep_->size == 0; }
|
||||
|
||||
// Return capacity of string
|
||||
size_type capacity () const { return rep_->capacity; }
|
||||
|
||||
|
||||
// single char extraction
|
||||
const char& at (size_type index) const
|
||||
{
|
||||
assert( index < length() );
|
||||
return rep_->str[ index ];
|
||||
}
|
||||
|
||||
// [] operator
|
||||
char& operator [] (size_type index) const
|
||||
{
|
||||
assert( index < length() );
|
||||
return rep_->str[ index ];
|
||||
}
|
||||
|
||||
// find a char in a string. Return TiXmlString::npos if not found
|
||||
size_type find (char lookup) const
|
||||
{
|
||||
return find(lookup, 0);
|
||||
}
|
||||
|
||||
// find a char in a string from an offset. Return TiXmlString::npos if not found
|
||||
size_type find (char tofind, size_type offset) const
|
||||
{
|
||||
if (offset >= length()) return npos;
|
||||
|
||||
for (const char* p = c_str() + offset; *p != '\0'; ++p)
|
||||
{
|
||||
if (*p == tofind) return static_cast< size_type >( p - c_str() );
|
||||
}
|
||||
return npos;
|
||||
}
|
||||
|
||||
void clear ()
|
||||
{
|
||||
//Lee:
|
||||
//The original was just too strange, though correct:
|
||||
// TiXmlString().swap(*this);
|
||||
//Instead use the quit & re-init:
|
||||
quit();
|
||||
init(0,0);
|
||||
}
|
||||
|
||||
/* Function to reserve a big amount of data when we know we'll need it. Be aware that this
|
||||
function DOES NOT clear the content of the TiXmlString if any exists.
|
||||
*/
|
||||
void reserve (size_type cap);
|
||||
|
||||
TiXmlString& assign (const char* str, size_type len);
|
||||
|
||||
TiXmlString& append (const char* str, size_type len);
|
||||
|
||||
void swap (TiXmlString& other)
|
||||
{
|
||||
Rep* r = rep_;
|
||||
rep_ = other.rep_;
|
||||
other.rep_ = r;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void init(size_type sz) { init(sz, sz); }
|
||||
void set_size(size_type sz) { rep_->str[ rep_->size = sz ] = '\0'; }
|
||||
char* start() const { return rep_->str; }
|
||||
char* finish() const { return rep_->str + rep_->size; }
|
||||
|
||||
struct Rep
|
||||
{
|
||||
size_type size, capacity;
|
||||
char str[1];
|
||||
};
|
||||
|
||||
void init(size_type sz, size_type cap)
|
||||
{
|
||||
if (cap)
|
||||
{
|
||||
// Lee: the original form:
|
||||
// rep_ = static_cast<Rep*>(operator new(sizeof(Rep) + cap));
|
||||
// doesn't work in some cases of new being overloaded. Switching
|
||||
// to the normal allocation, although use an 'int' for systems
|
||||
// that are overly picky about structure alignment.
|
||||
const size_type bytesNeeded = sizeof(Rep) + cap;
|
||||
const size_type intsNeeded = ( bytesNeeded + sizeof(int) - 1 ) / sizeof( int );
|
||||
rep_ = reinterpret_cast<Rep*>( new int[ intsNeeded ] );
|
||||
|
||||
rep_->str[ rep_->size = sz ] = '\0';
|
||||
rep_->capacity = cap;
|
||||
}
|
||||
else
|
||||
{
|
||||
rep_ = &nullrep_;
|
||||
}
|
||||
}
|
||||
|
||||
void quit()
|
||||
{
|
||||
if (rep_ != &nullrep_)
|
||||
{
|
||||
// The rep_ is really an array of ints. (see the allocator, above).
|
||||
// Cast it back before delete, so the compiler won't incorrectly call destructors.
|
||||
delete [] ( reinterpret_cast<int*>( rep_ ) );
|
||||
}
|
||||
}
|
||||
|
||||
Rep * rep_;
|
||||
static Rep nullrep_;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
inline bool operator == (const TiXmlString & a, const TiXmlString & b)
|
||||
{
|
||||
return ( a.length() == b.length() ) // optimization on some platforms
|
||||
&& ( strcmp(a.c_str(), b.c_str()) == 0 ); // actual compare
|
||||
}
|
||||
inline bool operator < (const TiXmlString & a, const TiXmlString & b)
|
||||
{
|
||||
return strcmp(a.c_str(), b.c_str()) < 0;
|
||||
}
|
||||
|
||||
inline bool operator != (const TiXmlString & a, const TiXmlString & b) { return !(a == b); }
|
||||
inline bool operator > (const TiXmlString & a, const TiXmlString & b) { return b < a; }
|
||||
inline bool operator <= (const TiXmlString & a, const TiXmlString & b) { return !(b < a); }
|
||||
inline bool operator >= (const TiXmlString & a, const TiXmlString & b) { return !(a < b); }
|
||||
|
||||
inline bool operator == (const TiXmlString & a, const char* b) { return strcmp(a.c_str(), b) == 0; }
|
||||
inline bool operator == (const char* a, const TiXmlString & b) { return b == a; }
|
||||
inline bool operator != (const TiXmlString & a, const char* b) { return !(a == b); }
|
||||
inline bool operator != (const char* a, const TiXmlString & b) { return !(b == a); }
|
||||
|
||||
TiXmlString operator + (const TiXmlString & a, const TiXmlString & b);
|
||||
TiXmlString operator + (const TiXmlString & a, const char* b);
|
||||
TiXmlString operator + (const char* a, const TiXmlString & b);
|
||||
|
||||
|
||||
/*
|
||||
TiXmlOutStream is an emulation of std::ostream. It is based on TiXmlString.
|
||||
Only the operators that we need for TinyXML have been developped.
|
||||
*/
|
||||
class GD_CORE_API TiXmlOutStream : public TiXmlString
|
||||
{
|
||||
public :
|
||||
|
||||
// TiXmlOutStream << operator.
|
||||
TiXmlOutStream & operator << (const TiXmlString & in)
|
||||
{
|
||||
*this += in;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// TiXmlOutStream << operator.
|
||||
TiXmlOutStream & operator << (const char * in)
|
||||
{
|
||||
*this += in;
|
||||
return *this;
|
||||
}
|
||||
|
||||
} ;
|
||||
|
||||
#endif // TIXML_STRING_INCLUDED
|
||||
#endif // TIXML_USE_STL
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
www.sourceforge.net/projects/tinyxml
|
||||
Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com)
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any
|
||||
damages arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any
|
||||
purpose, including commercial applications, and to alter it and
|
||||
redistribute it freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must
|
||||
not claim that you wrote the original software. If you use this
|
||||
software in a product, an acknowledgment in the product documentation
|
||||
would be appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and
|
||||
must not be misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*/
|
||||
|
||||
#include "GDCore/TinyXml/tinyxml.h"
|
||||
|
||||
// The goal of the seperate error file is to make the first
|
||||
// step towards localization. tinyxml (currently) only supports
|
||||
// english error messages, but the could now be translated.
|
||||
//
|
||||
// It also cleans up the code a bit.
|
||||
//
|
||||
|
||||
const char* TiXmlBase::errorString[ TIXML_ERROR_STRING_COUNT ] =
|
||||
{
|
||||
"No error",
|
||||
"Error",
|
||||
"Failed to open file",
|
||||
"Memory allocation failed.",
|
||||
"Error parsing Element.",
|
||||
"Failed to read Element name",
|
||||
"Error reading Element value.",
|
||||
"Error reading Attributes.",
|
||||
"Error: empty tag.",
|
||||
"Error reading end tag.",
|
||||
"Error parsing Unknown.",
|
||||
"Error parsing Comment.",
|
||||
"Error parsing Declaration.",
|
||||
"Error document empty.",
|
||||
"Error null (0) or unexpected EOF found in input stream.",
|
||||
"Error parsing CDATA.",
|
||||
"Error when TiXmlDocument added to document, because TiXmlDocument can only be at the root.",
|
||||
};
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -204,6 +204,10 @@ class SerializableWithNameList {
|
||||
|
||||
void UnserializeElementsFrom(const gd::String& elementName,
|
||||
const SerializerElement& element);
|
||||
|
||||
void ProgressivelyUnserializeElementsFrom(const gd::String& elementName,
|
||||
gd::Project& project,
|
||||
const SerializerElement& element);
|
||||
///@}
|
||||
|
||||
protected:
|
||||
|
@@ -127,6 +127,26 @@ void SerializableWithNameList<T>::SerializeElementsTo(
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void SerializableWithNameList<T>::ProgressivelyUnserializeElementsFrom(
|
||||
const gd::String& elementName,
|
||||
gd::Project& project,
|
||||
const SerializerElement& serializerElement) {
|
||||
serializerElement.ConsiderAsArrayOf(elementName);
|
||||
for (std::size_t i = 0; i < serializerElement.GetChildrenCount(); ++i) {
|
||||
T* newElement = nullptr;
|
||||
if (elements.size() <= i) {
|
||||
newElement = &InsertNew("", GetCount());
|
||||
} else {
|
||||
newElement = elements[i].get();
|
||||
}
|
||||
newElement->UnserializeFrom(project, serializerElement.GetChild(i));
|
||||
}
|
||||
while (elements.size() > serializerElement.GetChildrenCount()) {
|
||||
elements.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void SerializableWithNameList<T>::UnserializeElementsFrom(
|
||||
const gd::String& elementName,
|
||||
|
@@ -1,39 +0,0 @@
|
||||
#include "GDCore/Tools/XmlLoader.h"
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
namespace gd {
|
||||
|
||||
namespace {
|
||||
FILE* GetFileHandle(const gd::String& filename, const gd::String& mode) {
|
||||
#if defined(WINDOWS)
|
||||
return _wfopen(filename.ToWide().c_str(), mode.ToWide().c_str());
|
||||
#else
|
||||
return fopen(filename.ToLocale().c_str(), mode.ToLocale().c_str());
|
||||
#endif
|
||||
}
|
||||
} // namespace
|
||||
|
||||
bool GD_CORE_API LoadXmlFromFile(TiXmlDocument& doc,
|
||||
const gd::String& filepath) {
|
||||
FILE* xmlFile = GetFileHandle(filepath, "rb");
|
||||
if (!xmlFile) return false;
|
||||
|
||||
bool res = doc.LoadFile(xmlFile);
|
||||
fclose(xmlFile);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool GD_CORE_API SaveXmlToFile(const TiXmlDocument& doc,
|
||||
const gd::String& filepath) {
|
||||
FILE* xmlFile = GetFileHandle(filepath, "wb");
|
||||
if (!xmlFile) return false;
|
||||
|
||||
bool res = doc.SaveFile(xmlFile);
|
||||
fclose(xmlFile);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
} // namespace gd
|
@@ -1,17 +0,0 @@
|
||||
#ifndef GDCORE_XMLLOADER_H
|
||||
#define GDCORE_XMLLOADER_H
|
||||
|
||||
#include "GDCore/String.h"
|
||||
#include "GDCore/TinyXml/tinyxml.h"
|
||||
|
||||
namespace gd {
|
||||
|
||||
bool GD_CORE_API LoadXmlFromFile(TiXmlDocument& doc,
|
||||
const gd::String& filepath);
|
||||
|
||||
bool GD_CORE_API SaveXmlToFile(const TiXmlDocument& doc,
|
||||
const gd::String& filepath);
|
||||
|
||||
} // namespace gd
|
||||
|
||||
#endif
|
@@ -705,7 +705,7 @@ EXCLUDE_PATTERNS =
|
||||
# wildcard * is used, a substring. Examples: ANamespace, AClass,
|
||||
# AClass::ANamespace, ANamespace::*Test
|
||||
|
||||
EXCLUDE_SYMBOLS = TiXml*
|
||||
EXCLUDE_SYMBOLS =
|
||||
|
||||
# The EXAMPLE_PATH tag can be used to specify one or more files or
|
||||
# directories that contain example code fragments that are included (see
|
||||
|
@@ -94,7 +94,7 @@ TEST_CASE("ArbitraryResourceWorker", "[common][resources]") {
|
||||
spriteConfiguration.GetAnimations().AddAnimation(anim);
|
||||
|
||||
gd::Object obj("myObject", "", spriteConfiguration.Clone());
|
||||
project.InsertObject(obj, 0);
|
||||
project.GetObjects().InsertObject(obj, 0);
|
||||
|
||||
worker.files.clear();
|
||||
worker.images.clear();
|
||||
@@ -141,7 +141,7 @@ TEST_CASE("ArbitraryResourceWorker", "[common][resources]") {
|
||||
spriteConfiguration.GetAnimations().AddAnimation(anim);
|
||||
|
||||
gd::Object obj("myObject", "", spriteConfiguration.Clone());
|
||||
layout.InsertObject(obj, 0);
|
||||
layout.GetObjects().InsertObject(obj, 0);
|
||||
|
||||
worker.files.clear();
|
||||
worker.images.clear();
|
||||
@@ -378,8 +378,9 @@ TEST_CASE("ArbitraryResourceWorker", "[common][resources]") {
|
||||
auto& layout = project.InsertNewLayout("Scene", 0);
|
||||
layout.InsertNewLayer("MyLayer", 0);
|
||||
auto& layer = layout.GetLayer("MyLayer");
|
||||
auto& object = layout.InsertNewObject(project, "MyExtension::Sprite", "MyObject", 0);
|
||||
auto& effect = object.GetEffects().InsertNewEffect("MyEffect", 0);
|
||||
auto &object = layout.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "MyObject", 0);
|
||||
auto &effect = object.GetEffects().InsertNewEffect("MyEffect", 0);
|
||||
effect.SetEffectType("MyExtension::EffectWithResource");
|
||||
effect.SetStringParameter("texture", "res1");
|
||||
|
||||
@@ -440,7 +441,7 @@ TEST_CASE("ArbitraryResourceWorker", "[common][resources]") {
|
||||
spriteConfiguration.GetAnimations().AddAnimation(anim);
|
||||
|
||||
gd::Object obj("myObject", "", spriteConfiguration.Clone());
|
||||
layout.InsertObject(obj, 0);
|
||||
layout.GetObjects().InsertObject(obj, 0);
|
||||
|
||||
worker.files.clear();
|
||||
worker.images.clear();
|
||||
@@ -894,8 +895,9 @@ TEST_CASE("ArbitraryResourceWorker", "[common][resources]") {
|
||||
auto& layout = project.InsertNewLayout("Scene", 0);
|
||||
layout.InsertNewLayer("MyLayer", 0);
|
||||
auto& layer = layout.GetLayer("MyLayer");
|
||||
auto& object = layout.InsertNewObject(project, "MyExtension::Sprite", "MyObject", 0);
|
||||
auto& effect = object.GetEffects().InsertNewEffect("MyEffect", 0);
|
||||
auto &object = layout.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "MyObject", 0);
|
||||
auto &effect = object.GetEffects().InsertNewEffect("MyEffect", 0);
|
||||
effect.SetEffectType("MyExtension::EffectWithResource");
|
||||
effect.SetStringParameter("texture", "res1");
|
||||
|
||||
|
@@ -52,7 +52,7 @@ void AddAnotherEventsBasedExtensionWithDependency(gd::Project &project) {
|
||||
eventsBasedObject.SetFullName("My events based object");
|
||||
eventsBasedObject.SetDescription("An events based object for test");
|
||||
|
||||
gd::Object &object = eventsBasedObject.InsertNewObject(
|
||||
gd::Object &object = eventsBasedObject.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "MyObject", 0);
|
||||
gd::Behavior *behavior =
|
||||
object.AddNewBehavior(project, "MyEventsExtension::MyEventsBasedBehavior",
|
||||
@@ -65,8 +65,8 @@ void SetupProject(gd::Project &project, gd::Platform &platform) {
|
||||
AddEventsBasedExtension(project);
|
||||
|
||||
gd::Layout &layout = project.InsertNewLayout("Scene", 0);
|
||||
gd::Object &object =
|
||||
layout.InsertNewObject(project, "MyExtension::Sprite", "MyObject", 0);
|
||||
gd::Object &object = layout.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "MyObject", 0);
|
||||
gd::Behavior *behavior =
|
||||
object.AddNewBehavior(project, "MyEventsExtension::MyEventsBasedBehavior",
|
||||
"MyEventsBasedBehavior");
|
||||
@@ -127,7 +127,8 @@ TEST_CASE("BehaviorSerialization", "[common]") {
|
||||
gd::Platform platform;
|
||||
gd::Project writtenProject;
|
||||
SetupProject(writtenProject, platform);
|
||||
CheckBehaviorProperty(writtenProject.GetLayout("Scene"));
|
||||
CheckBehaviorProperty(
|
||||
writtenProject.GetLayout("Scene").GetObjects());
|
||||
|
||||
SerializerElement projectElement;
|
||||
writtenProject.SerializeTo(projectElement);
|
||||
@@ -136,7 +137,7 @@ TEST_CASE("BehaviorSerialization", "[common]") {
|
||||
gd::Project readProject;
|
||||
readProject.AddPlatform(platform);
|
||||
readProject.UnserializeFrom(projectElement);
|
||||
CheckBehaviorProperty(readProject.GetLayout("Scene"));
|
||||
CheckBehaviorProperty(readProject.GetLayout("Scene").GetObjects());
|
||||
}
|
||||
|
||||
SECTION("Load a project with a property value on a custom behavior that no longer exists") {
|
||||
@@ -158,7 +159,7 @@ TEST_CASE("BehaviorSerialization", "[common]") {
|
||||
// Add the events-based behavior back
|
||||
AddEventsBasedExtension(readProject);
|
||||
|
||||
CheckBehaviorProperty(readProject.GetLayout("Scene"));
|
||||
CheckBehaviorProperty(readProject.GetLayout("Scene").GetObjects());
|
||||
}
|
||||
|
||||
SECTION("Save and load a project with an event based extension dependency") {
|
||||
@@ -203,7 +204,9 @@ TEST_CASE("BehaviorSerialization", "[common]") {
|
||||
// extension.
|
||||
REQUIRE(readProject.HasEventsBasedObject(
|
||||
"MyOtherEventsExtension::MyEventsBasedObject"));
|
||||
CheckBehaviorProperty(readProject.GetEventsBasedObject(
|
||||
"MyOtherEventsExtension::MyEventsBasedObject"));
|
||||
CheckBehaviorProperty(
|
||||
readProject
|
||||
.GetEventsBasedObject("MyOtherEventsExtension::MyEventsBasedObject")
|
||||
.GetObjects());
|
||||
}
|
||||
}
|
@@ -80,7 +80,7 @@ TEST_CASE("EventsList", "[common][events]") {
|
||||
#if defined(WINDOWS)
|
||||
REQUIRE(3000 >= endMemory - startMemory);
|
||||
#else
|
||||
REQUIRE(1600 >= endMemory - startMemory);
|
||||
REQUIRE(1650 >= endMemory - startMemory);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@@ -39,8 +39,8 @@ TEST_CASE("EventsBehaviorRenamer (expressions)", "[common]") {
|
||||
auto projectScopedContainers =
|
||||
gd::ProjectScopedContainers::MakeNewProjectScopedContainersForProjectAndLayout(project, layout1);
|
||||
|
||||
auto &object1 =
|
||||
layout1.InsertNewObject(project, "MyExtension::Sprite", "Object1", 0);
|
||||
auto &object1 = layout1.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "Object1", 0);
|
||||
object1.AddNewBehavior(project, "MyExtension::MyBehavior", "MyBehavior");
|
||||
object1.AddNewBehavior(project, "MyExtension::MyBehavior", "MyBehavior2");
|
||||
|
||||
@@ -80,8 +80,8 @@ TEST_CASE("EventsBehaviorRenamer (instructions)", "[common]") {
|
||||
auto projectScopedContainers =
|
||||
gd::ProjectScopedContainers::MakeNewProjectScopedContainersForProjectAndLayout(project, layout1);
|
||||
|
||||
auto &object1 =
|
||||
layout1.InsertNewObject(project, "MyExtension::Sprite", "Object1", 0);
|
||||
auto &object1 = layout1.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "Object1", 0);
|
||||
object1.AddNewBehavior(project, "MyExtension::MyBehavior", "MyBehavior");
|
||||
object1.AddNewBehavior(project, "MyExtension::MyBehavior", "MyBehavior2");
|
||||
|
||||
|
@@ -63,7 +63,8 @@ TEST_CASE("Events-based extension", "[common]") {
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
auto &eventsExtension = SetupProjectWithEventsFunctionExtension(project);
|
||||
auto &layout1 = project.InsertNewLayout("Layout1", 0);
|
||||
auto &object = layout1.InsertNewObject(project, "MyExtension::Sprite", "Object1", 0);
|
||||
auto &object = layout1.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "Object1", 0);
|
||||
|
||||
// Attach a behavior to an object.
|
||||
auto *behavior = object.AddNewBehavior(project, "MyEventsExtension::MyEventsBasedBehavior", "MyEventsBasedBehavior");
|
||||
|
@@ -195,7 +195,8 @@ TEST_CASE("EventsIdentifiersFinder (object timers)", "[common]") {
|
||||
DeclareTimerExtension(project, platform);
|
||||
|
||||
auto &layout = project.InsertNewLayout("Layout1", 0);
|
||||
auto &object = layout.InsertNewObject(project, "", "MyObject", 0);
|
||||
auto &object = layout.GetObjects().InsertNewObject(project, "",
|
||||
"MyObject", 0);
|
||||
layout.GetEvents().InsertEvent(UseObjectTimer("MyObject", "MyObjectTimer"));
|
||||
|
||||
auto identifierExpressions =
|
||||
@@ -212,8 +213,10 @@ TEST_CASE("EventsIdentifiersFinder (object timers)", "[common]") {
|
||||
DeclareTimerExtension(project, platform);
|
||||
|
||||
auto &layout = project.InsertNewLayout("Layout1", 0);
|
||||
auto &object = layout.InsertNewObject(project, "", "MyObject", 0);
|
||||
layout.GetEvents().InsertEvent(UseObjectTimerInExpression("MyObject", "MyObjectTimer"));
|
||||
auto &object = layout.GetObjects().InsertNewObject(project, "",
|
||||
"MyObject", 0);
|
||||
layout.GetEvents().InsertEvent(
|
||||
UseObjectTimerInExpression("MyObject", "MyObjectTimer"));
|
||||
|
||||
auto identifierExpressions =
|
||||
gd::EventsIdentifiersFinder::FindAllIdentifierExpressions(
|
||||
@@ -229,7 +232,8 @@ TEST_CASE("EventsIdentifiersFinder (object timers)", "[common]") {
|
||||
DeclareTimerExtension(project, platform);
|
||||
|
||||
auto &layout = project.InsertNewLayout("Layout1", 0);
|
||||
auto &object = layout.InsertNewObject(project, "", "MyObject", 0);
|
||||
auto &object = layout.GetObjects().InsertNewObject(project, "",
|
||||
"MyObject", 0);
|
||||
auto &externalEvents = project.InsertNewExternalEvents("ExternalEvents", 0);
|
||||
externalEvents.GetEvents().InsertEvent(
|
||||
UseObjectTimer("MyObject", "MyObjectTimer"));
|
||||
@@ -249,8 +253,10 @@ TEST_CASE("EventsIdentifiersFinder (object timers)", "[common]") {
|
||||
DeclareTimerExtension(project, platform);
|
||||
|
||||
auto &layout = project.InsertNewLayout("Layout1", 0);
|
||||
auto &object1 = layout.InsertNewObject(project, "", "MyObject1", 0);
|
||||
auto &object2 = layout.InsertNewObject(project, "", "MyObject2", 0);
|
||||
auto &object1 = layout.GetObjects().InsertNewObject(
|
||||
project, "", "MyObject1", 0);
|
||||
auto &object2 = layout.GetObjects().InsertNewObject(
|
||||
project, "", "MyObject2", 0);
|
||||
layout.GetEvents().InsertEvent(
|
||||
UseObjectTimer("MyObject1", "MyObjectTimer1"));
|
||||
layout.GetEvents().InsertEvent(
|
||||
@@ -270,8 +276,10 @@ TEST_CASE("EventsIdentifiersFinder (object timers)", "[common]") {
|
||||
DeclareTimerExtension(project, platform);
|
||||
|
||||
auto &layout = project.InsertNewLayout("Layout1", 0);
|
||||
auto &object1 = layout.InsertNewObject(project, "", "MyObject1", 0);
|
||||
auto &object2 = layout.InsertNewObject(project, "", "MyObject2", 0);
|
||||
auto &object1 = layout.GetObjects().InsertNewObject(
|
||||
project, "", "MyObject1", 0);
|
||||
auto &object2 = layout.GetObjects().InsertNewObject(
|
||||
project, "", "MyObject2", 0);
|
||||
auto &externalEvents = project.InsertNewExternalEvents("ExternalEvents", 0);
|
||||
externalEvents.GetEvents().InsertEvent(
|
||||
UseObjectTimer("MyObject1", "MyObjectTimer1"));
|
||||
|
@@ -268,7 +268,8 @@ TEST_CASE("EventsVariablesFinder (FindAllObjectVariables)", "[common]") {
|
||||
DeclareVariableExtension(project, platform);
|
||||
|
||||
auto &layout = project.InsertNewLayout("Layout1", 0);
|
||||
auto &object = layout.InsertNewObject(project, "", "MyObject", 0);
|
||||
auto &object = layout.GetObjects().InsertNewObject(project, "",
|
||||
"MyObject", 0);
|
||||
layout.GetEvents().InsertEvent(
|
||||
UseObjectVariable("MyObject", "MyObjectVariable"));
|
||||
|
||||
@@ -285,7 +286,8 @@ TEST_CASE("EventsVariablesFinder (FindAllObjectVariables)", "[common]") {
|
||||
DeclareVariableExtension(project, platform);
|
||||
|
||||
auto &layout = project.InsertNewLayout("Layout1", 0);
|
||||
auto &object = layout.InsertNewObject(project, "", "MyObject", 0);
|
||||
auto &object = layout.GetObjects().InsertNewObject(project, "",
|
||||
"MyObject", 0);
|
||||
layout.GetEvents().InsertEvent(
|
||||
UseObjectVariableInExpression("MyObject", "MyObjectVariable"));
|
||||
|
||||
@@ -302,7 +304,8 @@ TEST_CASE("EventsVariablesFinder (FindAllObjectVariables)", "[common]") {
|
||||
DeclareVariableExtension(project, platform);
|
||||
|
||||
auto &layout = project.InsertNewLayout("Layout1", 0);
|
||||
auto &object = layout.InsertNewObject(project, "", "MyObject", 0);
|
||||
auto &object = layout.GetObjects().InsertNewObject(project, "",
|
||||
"MyObject", 0);
|
||||
auto &externalEvents = project.InsertNewExternalEvents("ExternalEvents", 0);
|
||||
externalEvents.GetEvents().InsertEvent(
|
||||
UseObjectVariable("MyObject", "MyObjectVariable"));
|
||||
@@ -321,8 +324,10 @@ TEST_CASE("EventsVariablesFinder (FindAllObjectVariables)", "[common]") {
|
||||
DeclareVariableExtension(project, platform);
|
||||
|
||||
auto &layout = project.InsertNewLayout("Layout1", 0);
|
||||
auto &object1 = layout.InsertNewObject(project, "", "MyObject1", 0);
|
||||
auto &object2 = layout.InsertNewObject(project, "", "MyObject2", 0);
|
||||
auto &object1 = layout.GetObjects().InsertNewObject(
|
||||
project, "", "MyObject1", 0);
|
||||
auto &object2 = layout.GetObjects().InsertNewObject(
|
||||
project, "", "MyObject2", 0);
|
||||
layout.GetEvents().InsertEvent(
|
||||
UseObjectVariable("MyObject1", "MyObjectVariable1"));
|
||||
layout.GetEvents().InsertEvent(
|
||||
@@ -342,8 +347,10 @@ TEST_CASE("EventsVariablesFinder (FindAllObjectVariables)", "[common]") {
|
||||
DeclareVariableExtension(project, platform);
|
||||
|
||||
auto &layout = project.InsertNewLayout("Layout1", 0);
|
||||
auto &object1 = layout.InsertNewObject(project, "", "MyObject1", 0);
|
||||
auto &object2 = layout.InsertNewObject(project, "", "MyObject2", 0);
|
||||
auto &object1 = layout.GetObjects().InsertNewObject(
|
||||
project, "", "MyObject1", 0);
|
||||
auto &object2 = layout.GetObjects().InsertNewObject(
|
||||
project, "", "MyObject2", 0);
|
||||
auto &externalEvents = project.InsertNewExternalEvents("ExternalEvents", 0);
|
||||
externalEvents.GetEvents().InsertEvent(
|
||||
UseObjectVariable("MyObject1", "MyObjectVariable1"));
|
||||
|
@@ -46,31 +46,39 @@ TEST_CASE("ExpressionCodeGenerator", "[common][events]") {
|
||||
variable.PushNew().SetString("3");
|
||||
}
|
||||
|
||||
auto &mySpriteObject = layout1.InsertNewObject(project, "MyExtension::Sprite", "MySpriteObject", 0);
|
||||
auto &mySpriteObject = layout1.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "MySpriteObject", 0);
|
||||
mySpriteObject.GetVariables().InsertNew("MyNumberVariable").SetValue(123);
|
||||
mySpriteObject.GetVariables().InsertNew("MyStringVariable").SetString("Test");
|
||||
mySpriteObject.GetVariables().InsertNew("MyStructureVariable").GetChild("MyStringChild").SetString("Test");
|
||||
layout1.InsertNewObject(
|
||||
project, "MyExtension::Sprite", "MyOtherSpriteObject", 1);
|
||||
layout1.InsertNewObject(project,
|
||||
"MyExtension::FakeObjectWithDefaultBehavior",
|
||||
"FakeObjectWithDefaultBehavior",
|
||||
2);
|
||||
mySpriteObject.GetVariables()
|
||||
.InsertNew("MyStructureVariable")
|
||||
.GetChild("MyStringChild")
|
||||
.SetString("Test");
|
||||
layout1.GetObjects().InsertNewObject(project, "MyExtension::Sprite",
|
||||
"MyOtherSpriteObject", 1);
|
||||
layout1.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::FakeObjectWithDefaultBehavior",
|
||||
"FakeObjectWithDefaultBehavior", 2);
|
||||
|
||||
// Also insert a variable having the same name as an object:
|
||||
layout1.InsertNewObject(project, "MyExtension::Sprite", "ObjectWithNameReused", 3);
|
||||
layout1.GetVariables().InsertNew("ObjectWithNameReused", 3).GetChild("MyChild");
|
||||
layout1.GetObjects().InsertNewObject(project, "MyExtension::Sprite",
|
||||
"ObjectWithNameReused", 3);
|
||||
layout1.GetVariables()
|
||||
.InsertNew("ObjectWithNameReused", 3)
|
||||
.GetChild("MyChild");
|
||||
|
||||
// Also insert a global variable having the same name as a scene variable:
|
||||
layout1.GetVariables().InsertNew("SceneVariableWithNameReused", 4);
|
||||
project.GetVariables().InsertNew("SceneVariableWithNameReused", 0);
|
||||
|
||||
auto &group = layout1.GetObjectGroups().InsertNew("AllObjects");
|
||||
auto &group =
|
||||
layout1.GetObjects().GetObjectGroups().InsertNew("AllObjects");
|
||||
group.AddObject("MySpriteObject");
|
||||
group.AddObject("MyOtherSpriteObject");
|
||||
group.AddObject("FakeObjectWithDefaultBehavior");
|
||||
|
||||
auto &spriteGroup = layout1.GetObjectGroups().InsertNew("MySpriteObjects");
|
||||
auto &spriteGroup = layout1.GetObjects().GetObjectGroups().InsertNew(
|
||||
"MySpriteObjects");
|
||||
spriteGroup.AddObject("MySpriteObject");
|
||||
spriteGroup.AddObject("MyOtherSpriteObject");
|
||||
|
||||
|
@@ -23,8 +23,8 @@ TEST_CASE("ExpressionCompletionFinder", "[common][events]") {
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
auto& layout1 = project.InsertNewLayout("Layout1", 0);
|
||||
layout1.GetVariables().InsertNew("myVariable");
|
||||
auto& object1 =
|
||||
layout1.InsertNewObject(project, "MyExtension::Sprite", "MyObject", 0);
|
||||
auto &object1 = layout1.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "MyObject", 0);
|
||||
object1.GetVariables().InsertNew("myObjectVariable");
|
||||
|
||||
gd::ProjectScopedContainers projectScopedContainers =
|
||||
|
@@ -57,7 +57,8 @@ TEST_CASE("ExpressionNodeLocationFinder", "[common][events]") {
|
||||
gd::Platform platform;
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
auto& layout1 = project.InsertNewLayout("Layout1", 0);
|
||||
layout1.InsertNewObject(project, "MyExtension::Sprite", "MySpriteObject", 0);
|
||||
layout1.GetObjects().InsertNewObject(project, "MyExtension::Sprite",
|
||||
"MySpriteObject", 0);
|
||||
|
||||
gd::ExpressionParser2 parser;
|
||||
|
||||
|
@@ -35,29 +35,36 @@ TEST_CASE("ExpressionParser2", "[common][events]") {
|
||||
|
||||
// Create an instance of BuiltinObject.
|
||||
// This is not possible in practice.
|
||||
auto &myObject = layout1.InsertNewObject(project, "", "MyObject", 0);
|
||||
auto &myObject =
|
||||
layout1.GetObjects().InsertNewObject(project, "", "MyObject", 0);
|
||||
myObject.AddNewBehavior(project, "MyExtension::MyBehavior", "MyBehavior");
|
||||
|
||||
auto &myGroup = layout1.GetObjectGroups().InsertNew("MyGroup");
|
||||
auto &myGroup =
|
||||
layout1.GetObjects().GetObjectGroups().InsertNew("MyGroup");
|
||||
myGroup.AddObject(myObject.GetName());
|
||||
|
||||
layout1.GetObjectGroups().InsertNew("EmptyGroup");
|
||||
layout1.GetObjects().GetObjectGroups().InsertNew("EmptyGroup");
|
||||
|
||||
auto &mySpriteObject = layout1.InsertNewObject(project, "MyExtension::Sprite", "MySpriteObject", 1);
|
||||
auto &mySpriteObject = layout1.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "MySpriteObject", 1);
|
||||
mySpriteObject.GetVariables().InsertNew("MyVariable");
|
||||
mySpriteObject.GetVariables().InsertNew("MyVariable2");
|
||||
mySpriteObject.GetVariables().InsertNew("MyVariable3");
|
||||
mySpriteObject.GetVariables().InsertNew("MyNumberVariable").SetValue(123);
|
||||
mySpriteObject.GetVariables().InsertNew("MyStringVariable").SetString("Test");
|
||||
auto &mySpriteObject2 = layout1.InsertNewObject(project, "MyExtension::Sprite", "MySpriteObject2", 1);
|
||||
// A variable with the same name as the object.
|
||||
mySpriteObject.GetVariables().InsertNew("MySpriteObject");
|
||||
auto &mySpriteObject2 = layout1.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "MySpriteObject2", 1);
|
||||
mySpriteObject2.GetVariables().InsertNew("MyVariable", 0);
|
||||
mySpriteObject2.GetVariables().InsertNew("MyVariable2", 1);
|
||||
layout1.InsertNewObject(project,
|
||||
"MyExtension::FakeObjectWithDefaultBehavior",
|
||||
"FakeObjectWithDefaultBehavior",
|
||||
2);
|
||||
layout1.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::FakeObjectWithDefaultBehavior",
|
||||
"FakeObjectWithDefaultBehavior", 2);
|
||||
|
||||
auto &mySpriteGroup = layout1.GetObjectGroups().InsertNew("MySpriteObjects", 0);
|
||||
auto &mySpriteGroup =
|
||||
layout1.GetObjects().GetObjectGroups().InsertNew(
|
||||
"MySpriteObjects", 0);
|
||||
mySpriteGroup.AddObject("MySpriteObject");
|
||||
mySpriteGroup.AddObject("MySpriteObject2");
|
||||
|
||||
@@ -1685,6 +1692,27 @@ TEST_CASE("ExpressionParser2", "[common][events]") {
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Variable with the same name as an object") {
|
||||
auto node = parser.ParseExpression("MySpriteObject.MySpriteObject");
|
||||
REQUIRE(node != nullptr);
|
||||
|
||||
gd::ExpressionValidator validator(platform, projectScopedContainers,
|
||||
"number|string");
|
||||
node->Visit(validator);
|
||||
REQUIRE(validator.GetFatalErrors().size() == 0);
|
||||
REQUIRE(validator.GetAllErrors().size() == 0);
|
||||
}
|
||||
|
||||
SECTION("Variable with the same name as an object (with child-variables)") {
|
||||
auto node = parser.ParseExpression("MySpriteObject.MySpriteObject.MyChild.MyChild");
|
||||
REQUIRE(node != nullptr);
|
||||
|
||||
gd::ExpressionValidator validator(platform, projectScopedContainers, "number|string");
|
||||
node->Visit(validator);
|
||||
REQUIRE(validator.GetFatalErrors().size() == 0);
|
||||
REQUIRE(validator.GetAllErrors().size() == 0);
|
||||
}
|
||||
|
||||
SECTION("Invalid object variables (1 level, non existing object)") {
|
||||
{
|
||||
auto node =
|
||||
@@ -2785,6 +2813,33 @@ TEST_CASE("ExpressionParser2", "[common][events]") {
|
||||
"No variable with this name found.");
|
||||
}
|
||||
|
||||
SECTION("Variable name collision with an object") {
|
||||
auto node = parser.ParseExpression("MySpriteObject");
|
||||
REQUIRE(node != nullptr);
|
||||
|
||||
gd::ExpressionValidator validator(platform, projectScopedContainers,
|
||||
"variable");
|
||||
node->Visit(validator);
|
||||
REQUIRE(validator.GetFatalErrors().size() == 0);
|
||||
REQUIRE(validator.GetAllErrors().size() == 1);
|
||||
REQUIRE(validator.GetAllErrors()[0]->GetMessage() ==
|
||||
"This variable has the same name as an object. Consider renaming "
|
||||
"one or the other.");
|
||||
}
|
||||
|
||||
SECTION("Variable name collision with an object (with child-variables)") {
|
||||
auto node = parser.ParseExpression("MySpriteObject.MyChild.MyChild");
|
||||
REQUIRE(node != nullptr);
|
||||
|
||||
gd::ExpressionValidator validator(platform, projectScopedContainers, "variable");
|
||||
node->Visit(validator);
|
||||
REQUIRE(validator.GetFatalErrors().size() == 0);
|
||||
REQUIRE(validator.GetAllErrors().size() == 1);
|
||||
REQUIRE(validator.GetAllErrors()[0]->GetMessage() ==
|
||||
"This variable has the same name as an object. Consider renaming "
|
||||
"one or the other.");
|
||||
}
|
||||
|
||||
SECTION("Declared scene variable") {
|
||||
auto node = parser.ParseExpression("MySceneVariable");
|
||||
REQUIRE(node != nullptr);
|
||||
|
@@ -20,7 +20,8 @@ TEST_CASE("ExpressionParser2 - Benchmarks", "[common][events]") {
|
||||
gd::Platform platform;
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
auto &layout1 = project.InsertNewLayout("Layout1", 0);
|
||||
layout1.InsertNewObject(project, "MyExtension::Sprite", "MySpriteObject", 0);
|
||||
layout1.GetObjects().InsertNewObject(project, "MyExtension::Sprite",
|
||||
"MySpriteObject", 0);
|
||||
|
||||
auto projectScopedContainers = gd::ProjectScopedContainers::MakeNewProjectScopedContainersForProjectAndLayout(project, layout1);
|
||||
|
||||
|
@@ -19,7 +19,8 @@ TEST_CASE("ExpressionParser2 - Naughty strings", "[common][events]") {
|
||||
gd::Platform platform;
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
auto &layout1 = project.InsertNewLayout("Layout1", 0);
|
||||
layout1.InsertNewObject(project, "MyExtension::Sprite", "MySpriteObject", 0);
|
||||
layout1.GetObjects().InsertNewObject(project, "MyExtension::Sprite",
|
||||
"MySpriteObject", 0);
|
||||
|
||||
gd::ExpressionParser2 parser;
|
||||
|
||||
|
@@ -18,7 +18,8 @@ TEST_CASE("ExpressionParser2NodePrinter", "[common][events]") {
|
||||
gd::Platform platform;
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
auto &layout1 = project.InsertNewLayout("Layout1", 0);
|
||||
layout1.InsertNewObject(project, "MyExtension::Sprite", "MySpriteObject", 0);
|
||||
layout1.GetObjects().InsertNewObject(project, "MyExtension::Sprite",
|
||||
"MySpriteObject", 0);
|
||||
|
||||
gd::ExpressionParser2 parser;
|
||||
|
||||
|
@@ -25,13 +25,13 @@ TEST_CASE("Layout", "[common]") {
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
|
||||
gd::Layout &layout = project.InsertNewLayout("Scene", 0);
|
||||
gd::Object &object =
|
||||
layout.InsertNewObject(project, "MyExtension::Sprite", "MyObject", 0);
|
||||
gd::Object &object = layout.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "MyObject", 0);
|
||||
object.AddNewBehavior(project, "MyExtension::MyBehavior", "MyBehavior");
|
||||
|
||||
REQUIRE(GetTypeOfBehaviorInObjectOrGroup(project, layout, "MyObject",
|
||||
"MyBehavior", true) ==
|
||||
"MyExtension::MyBehavior");
|
||||
REQUIRE(GetTypeOfBehaviorInObjectOrGroup(
|
||||
project.GetObjects(), layout.GetObjects(),
|
||||
"MyObject", "MyBehavior", true) == "MyExtension::MyBehavior");
|
||||
}
|
||||
|
||||
SECTION("Give an empty type for an object that doesn't have the behavior") {
|
||||
@@ -40,11 +40,12 @@ TEST_CASE("Layout", "[common]") {
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
|
||||
gd::Layout &layout = project.InsertNewLayout("Scene", 0);
|
||||
gd::Object &object =
|
||||
layout.InsertNewObject(project, "MyExtension::Sprite", "MyObject", 0);
|
||||
gd::Object &object = layout.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "MyObject", 0);
|
||||
|
||||
REQUIRE(GetTypeOfBehaviorInObjectOrGroup(project, layout, "MyObject",
|
||||
"MyBehavior", true) == "");
|
||||
REQUIRE(GetTypeOfBehaviorInObjectOrGroup(
|
||||
project.GetObjects(), layout.GetObjects(),
|
||||
"MyObject", "MyBehavior", true) == "");
|
||||
}
|
||||
|
||||
SECTION("Find the type of a behavior in a group") {
|
||||
@@ -53,63 +54,70 @@ TEST_CASE("Layout", "[common]") {
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
|
||||
gd::Layout &layout = project.InsertNewLayout("Scene", 0);
|
||||
gd::Object &object1 =
|
||||
layout.InsertNewObject(project, "MyExtension::Sprite", "MyObject1", 0);
|
||||
gd::Object &object1 = layout.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "MyObject1", 0);
|
||||
object1.AddNewBehavior(project, "MyExtension::MyBehavior", "MyBehavior");
|
||||
gd::Object &object2 =
|
||||
layout.InsertNewObject(project, "MyExtension::Sprite", "MyObject2", 0);
|
||||
gd::Object &object2 = layout.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "MyObject2", 0);
|
||||
object2.AddNewBehavior(project, "MyExtension::MyBehavior", "MyBehavior");
|
||||
|
||||
auto &group = layout.GetObjectGroups().InsertNew("MyGroup", 0);
|
||||
auto &group =
|
||||
layout.GetObjects().GetObjectGroups().InsertNew("MyGroup", 0);
|
||||
group.AddObject(object1.GetName());
|
||||
group.AddObject(object2.GetName());
|
||||
|
||||
REQUIRE(GetTypeOfBehaviorInObjectOrGroup(project, layout, "MyGroup",
|
||||
"MyBehavior", true) ==
|
||||
"MyExtension::MyBehavior");
|
||||
REQUIRE(GetTypeOfBehaviorInObjectOrGroup(
|
||||
project.GetObjects(), layout.GetObjects(),
|
||||
"MyGroup", "MyBehavior", true) == "MyExtension::MyBehavior");
|
||||
}
|
||||
|
||||
SECTION("Give an empty type for a group with an object missing the behavior") {
|
||||
SECTION(
|
||||
"Give an empty type for a group with an object missing the behavior") {
|
||||
gd::Platform platform;
|
||||
gd::Project project;
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
|
||||
gd::Layout &layout = project.InsertNewLayout("Scene", 0);
|
||||
gd::Object &object1 =
|
||||
layout.InsertNewObject(project, "MyExtension::Sprite", "MyObject1", 0);
|
||||
gd::Object &object1 = layout.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "MyObject1", 0);
|
||||
object1.AddNewBehavior(project, "MyExtension::MyBehavior", "MyBehavior");
|
||||
gd::Object &object2 =
|
||||
layout.InsertNewObject(project, "MyExtension::Sprite", "MyObject2", 0);
|
||||
gd::Object &object2 = layout.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "MyObject2", 0);
|
||||
// object2 doesn't have the behavior.
|
||||
|
||||
auto &group = layout.GetObjectGroups().InsertNew("MyGroup", 0);
|
||||
auto &group =
|
||||
layout.GetObjects().GetObjectGroups().InsertNew("MyGroup", 0);
|
||||
group.AddObject(object1.GetName());
|
||||
group.AddObject(object2.GetName());
|
||||
|
||||
REQUIRE(GetTypeOfBehaviorInObjectOrGroup(project, layout, "MyGroup",
|
||||
"MyBehavior", true) == "");
|
||||
REQUIRE(GetTypeOfBehaviorInObjectOrGroup(
|
||||
project.GetObjects(), layout.GetObjects(),
|
||||
"MyGroup", "MyBehavior", true) == "");
|
||||
}
|
||||
|
||||
SECTION("Give an empty type for a group with behaviors of same name but different types") {
|
||||
SECTION("Give an empty type for a group with behaviors of same name but "
|
||||
"different types") {
|
||||
gd::Platform platform;
|
||||
gd::Project project;
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
|
||||
gd::Layout &layout = project.InsertNewLayout("Scene", 0);
|
||||
gd::Object &object1 =
|
||||
layout.InsertNewObject(project, "MyExtension::Sprite", "MyObject1", 0);
|
||||
gd::Object &object1 = layout.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "MyObject1", 0);
|
||||
object1.AddNewBehavior(project, "MyExtension::MyBehavior", "MyBehavior");
|
||||
gd::Object &object2 =
|
||||
layout.InsertNewObject(project, "MyExtension::Sprite", "MyObject2", 0);
|
||||
gd::Object &object2 = layout.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "MyObject2", 0);
|
||||
object2.AddNewBehavior(project, "MyExtension::MyOtherBehavior",
|
||||
"MyBehavior");
|
||||
|
||||
auto &group = layout.GetObjectGroups().InsertNew("MyGroup", 0);
|
||||
auto &group =
|
||||
layout.GetObjects().GetObjectGroups().InsertNew("MyGroup", 0);
|
||||
group.AddObject(object1.GetName());
|
||||
group.AddObject(object2.GetName());
|
||||
|
||||
REQUIRE(GetTypeOfBehaviorInObjectOrGroup(project, layout, "MyGroup",
|
||||
"MyBehavior", true) == "");
|
||||
REQUIRE(GetTypeOfBehaviorInObjectOrGroup(
|
||||
project.GetObjects(), layout.GetObjects(),
|
||||
"MyGroup", "MyBehavior", true) == "");
|
||||
}
|
||||
|
||||
SECTION("Give an empty type for an empty group") {
|
||||
@@ -118,9 +126,11 @@ TEST_CASE("Layout", "[common]") {
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
|
||||
gd::Layout &layout = project.InsertNewLayout("Scene", 0);
|
||||
auto &group = layout.GetObjectGroups().InsertNew("MyGroup", 0);
|
||||
auto &group =
|
||||
layout.GetObjects().GetObjectGroups().InsertNew("MyGroup", 0);
|
||||
|
||||
REQUIRE(GetTypeOfBehaviorInObjectOrGroup(project, layout, "MyGroup",
|
||||
"MyBehavior", true) == "");
|
||||
REQUIRE(GetTypeOfBehaviorInObjectOrGroup(
|
||||
project.GetObjects(), layout.GetObjects(),
|
||||
"MyGroup", "MyBehavior", true) == "");
|
||||
}
|
||||
}
|
@@ -36,7 +36,7 @@ TEST_CASE("Object", "[common]") {
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
|
||||
gd::Layout &layout = project.InsertNewLayout("Scene", 0);
|
||||
gd::Object &object = layout.InsertNewObject(
|
||||
gd::Object &object = layout.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::FakeObjectWithDefaultBehavior", "MyObject", 0);
|
||||
|
||||
REQUIRE(object.HasBehaviorNamed("Effect"));
|
||||
|
@@ -43,8 +43,8 @@ TEST_CASE("ObjectAssetSerializer", "[common]") {
|
||||
"MyEventsBasedObject", 0);
|
||||
eventsBasedObject.SetFullName("My events based object");
|
||||
eventsBasedObject.SetDescription("An events based object for test");
|
||||
eventsBasedObject.InsertNewObject(project, "MyExtension::Sprite", "MyChild",
|
||||
0);
|
||||
eventsBasedObject.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "MyChild", 0);
|
||||
|
||||
auto &resourceManager = project.GetResourcesManager();
|
||||
gd::ImageResource imageResource;
|
||||
@@ -54,7 +54,7 @@ TEST_CASE("ObjectAssetSerializer", "[common]") {
|
||||
resourceManager.AddResource(imageResource);
|
||||
|
||||
gd::Layout &layout = project.InsertNewLayout("Scene", 0);
|
||||
gd::Object &object = layout.InsertNewObject(
|
||||
gd::Object &object = layout.GetObjects().InsertNewObject(
|
||||
project, "MyEventsExtension::MyEventsBasedObject", "MyObject", 0);
|
||||
auto &configuration = object.GetConfiguration();
|
||||
auto *customObjectConfiguration =
|
||||
|
@@ -43,8 +43,8 @@ gd::Object &SetupProjectWithSprite(gd::Project &project,
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
|
||||
gd::Layout &layout = project.InsertNewLayout("Scene", 0);
|
||||
gd::Object &object =
|
||||
layout.InsertNewObject(project, "MyExtension::Sprite", "MyObject", 0);
|
||||
gd::Object &object = layout.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "MyObject", 0);
|
||||
SetupSpriteConfiguration(object.GetConfiguration());
|
||||
|
||||
return object;
|
||||
@@ -98,7 +98,7 @@ void CheckSpriteConfiguration(gd::Object &object) {
|
||||
|
||||
void CheckSpriteConfiguration(gd::Project &project) {
|
||||
auto &layout = project.GetLayout("Scene");
|
||||
auto &object = layout.GetObject("MyObject");
|
||||
auto &object = layout.GetObjects().GetObject("MyObject");
|
||||
CheckSpriteConfiguration(object);
|
||||
};
|
||||
|
||||
@@ -112,11 +112,11 @@ gd::Object &SetupProjectWithCustomObject(gd::Project &project,
|
||||
"MyEventsBasedObject", 0);
|
||||
eventsBasedObject.SetFullName("My events based object");
|
||||
eventsBasedObject.SetDescription("An events based object for test");
|
||||
eventsBasedObject.InsertNewObject(project, "MyExtension::Sprite", "MyChild",
|
||||
0);
|
||||
eventsBasedObject.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "MyChild", 0);
|
||||
|
||||
gd::Layout &layout = project.InsertNewLayout("Scene", 0);
|
||||
gd::Object &object = layout.InsertNewObject(
|
||||
gd::Object &object = layout.GetObjects().InsertNewObject(
|
||||
project, "MyEventsExtension::MyEventsBasedObject", "MyObject", 0);
|
||||
auto &configuration = object.GetConfiguration();
|
||||
auto *customObjectConfiguration =
|
||||
@@ -167,7 +167,7 @@ void CheckCustomObjectConfiguration(gd::Object &object) {
|
||||
|
||||
void CheckCustomObjectConfiguration(gd::Project &project) {
|
||||
auto &layout = project.GetLayout("Scene");
|
||||
auto &object = layout.GetObject("MyObject");
|
||||
auto &object = layout.GetObjects().GetObject("MyObject");
|
||||
CheckCustomObjectConfiguration(object);
|
||||
};
|
||||
} // namespace
|
||||
@@ -232,7 +232,7 @@ TEST_CASE("ObjectSerialization", "[common]") {
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
|
||||
gd::Layout &layout = project.InsertNewLayout("Scene", 0);
|
||||
gd::Object &object = layout.InsertNewObject(
|
||||
gd::Object &object = layout.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::FakeObjectWithDefaultBehavior", "MyObject", 0);
|
||||
REQUIRE(object.HasBehaviorNamed("Effect"));
|
||||
|
||||
|
@@ -79,15 +79,15 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
|
||||
.SetValue(123);
|
||||
|
||||
// Declare variables in objects.
|
||||
auto &object1 =
|
||||
layout1.InsertNewObject(project, "MyExtension::Sprite", "Object1", 0);
|
||||
auto &object1 = layout1.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "Object1", 0);
|
||||
object1.GetVariables().InsertNew("MyObjectVariable");
|
||||
object1.GetVariables()
|
||||
.InsertNew("MyObjectStructureVariable")
|
||||
.GetChild("MyChild")
|
||||
.SetValue(123);
|
||||
auto &object2 =
|
||||
layout1.InsertNewObject(project, "MyExtension::Sprite", "Object2", 0);
|
||||
auto &object2 = layout1.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "Object2", 0);
|
||||
object2.GetVariables().InsertNew("MyObjectVariable");
|
||||
object2.GetVariables()
|
||||
.InsertNew("MyObjectStructureVariable")
|
||||
@@ -339,22 +339,23 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
|
||||
project, "BuiltinCommonInstructions::Repeat"));
|
||||
|
||||
// Declare variables in objects.
|
||||
auto &object1 =
|
||||
layout1.InsertNewObject(project, "MyExtension::Sprite", "Object1", 0);
|
||||
auto &object1 = layout1.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "Object1", 0);
|
||||
object1.GetVariables().InsertNew("MyObjectVariable");
|
||||
object1.GetVariables()
|
||||
.InsertNew("MyObjectStructureVariable")
|
||||
.GetChild("MyChild")
|
||||
.SetValue(123);
|
||||
auto &object2 =
|
||||
layout1.InsertNewObject(project, "MyExtension::Sprite", "Object2", 0);
|
||||
auto &object2 = layout1.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "Object2", 0);
|
||||
object2.GetVariables().InsertNew("MyObjectVariable");
|
||||
object2.GetVariables()
|
||||
.InsertNew("MyObjectStructureVariable")
|
||||
.GetChild("MyChild")
|
||||
.SetValue(123);
|
||||
|
||||
auto& group = layout1.GetObjectGroups().InsertNew("MyObjectGroup");
|
||||
auto &group = layout1.GetObjects().GetObjectGroups().InsertNew(
|
||||
"MyObjectGroup");
|
||||
group.AddObject("Object1");
|
||||
group.AddObject("Object2");
|
||||
|
||||
@@ -536,15 +537,15 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
|
||||
.SetValue(123);
|
||||
|
||||
// Declare variables in objects.
|
||||
auto &object1 =
|
||||
layout1.InsertNewObject(project, "MyExtension::Sprite", "Object1", 0);
|
||||
auto &object1 = layout1.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "Object1", 0);
|
||||
object1.GetVariables().InsertNew("MyObjectVariable");
|
||||
object1.GetVariables()
|
||||
.InsertNew("MyObjectStructureVariable")
|
||||
.GetChild("MyChild")
|
||||
.SetValue(123);
|
||||
auto &object2 =
|
||||
layout1.InsertNewObject(project, "MyExtension::Sprite", "Object2", 0);
|
||||
auto &object2 = layout1.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "Object2", 0);
|
||||
object2.GetVariables().InsertNew("MyObjectVariable");
|
||||
object2.GetVariables()
|
||||
.InsertNew("MyObjectStructureVariable")
|
||||
@@ -959,8 +960,8 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
|
||||
auto &scene = project.InsertNewLayout("Scene", 0);
|
||||
auto &object =
|
||||
scene.InsertNewObject(project, "MyExtension::Sprite", "Object", 0);
|
||||
auto &object = scene.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "Object", 0);
|
||||
object.GetVariables()
|
||||
.InsertNew("MyVariable")
|
||||
.GetChild("MyChild")
|
||||
@@ -1009,8 +1010,8 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
|
||||
auto &scene = project.InsertNewLayout("Scene", 0);
|
||||
auto &object =
|
||||
scene.InsertNewObject(project, "MyExtension::Sprite", "Object", 0);
|
||||
auto &object = scene.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "Object", 0);
|
||||
object.GetVariables()
|
||||
.InsertNew("MyVariable")
|
||||
.GetChild("MyChild")
|
||||
@@ -1057,8 +1058,8 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
|
||||
auto &scene = project.InsertNewLayout("Scene", 0);
|
||||
auto &object =
|
||||
scene.InsertNewObject(project, "MyExtension::Sprite", "Object", 0);
|
||||
auto &object = scene.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "Object", 0);
|
||||
object.GetVariables()
|
||||
.InsertNew("MyVariable")
|
||||
.GetChild("MyChild")
|
||||
@@ -1795,8 +1796,8 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
|
||||
auto &scene = project.InsertNewLayout("Scene", 0);
|
||||
auto &object =
|
||||
scene.InsertNewObject(project, "MyExtension::Sprite", "Object", 0);
|
||||
auto &object = scene.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "Object", 0);
|
||||
object.GetVariables().InsertNew("MyObjectVariable").SetValue(123);
|
||||
|
||||
gd::StandardEvent &event =
|
||||
@@ -1840,8 +1841,8 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
|
||||
auto &scene = project.InsertNewLayout("Scene", 0);
|
||||
auto &object =
|
||||
scene.InsertNewObject(project, "MyExtension::Sprite", "Object", 0);
|
||||
auto &object = scene.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "Object", 0);
|
||||
object.GetVariables()
|
||||
.InsertNew("MyObjectVariable")
|
||||
.GetChild("MyChild")
|
||||
|
@@ -27,6 +27,7 @@
|
||||
#include "GDCore/Project/Layout.h"
|
||||
#include "GDCore/Project/Object.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/Project/ProjectScopedContainers.h"
|
||||
#include "GDCore/Project/Variable.h"
|
||||
#include "catch.hpp"
|
||||
|
||||
@@ -1069,15 +1070,20 @@ SetupProjectWithEventsFunctionExtension(gd::Project &project) {
|
||||
|
||||
// Add a child-object with the same names the one from the scene
|
||||
// to be able to use the same events list.
|
||||
auto &childObject = eventsBasedObject.InsertNewObject(
|
||||
auto &childObject = eventsBasedObject.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "ObjectWithMyBehavior", 0);
|
||||
childObject.AddNewBehavior(project, "MyEventsExtension::MyEventsBasedBehavior", "MyBehavior");
|
||||
childObject.AddNewBehavior(
|
||||
project, "MyEventsExtension::MyEventsBasedBehavior", "MyBehavior");
|
||||
childObject.GetVariables().InsertNew("MyVariable");
|
||||
childObject.GetVariables().InsertNew("MyStructureVariable").CastTo(gd::Variable::Structure);
|
||||
auto &group = eventsBasedObject.GetObjectGroups().InsertNew("GroupWithMyBehavior");
|
||||
childObject.GetVariables()
|
||||
.InsertNew("MyStructureVariable")
|
||||
.CastTo(gd::Variable::Structure);
|
||||
auto &group =
|
||||
eventsBasedObject.GetObjects().GetObjectGroups().InsertNew(
|
||||
"GroupWithMyBehavior");
|
||||
group.AddObject(childObject.GetName());
|
||||
|
||||
eventsBasedObject.InsertNewObject(
|
||||
eventsBasedObject.GetObjects().InsertNewObject(
|
||||
project, "MyEventsExtension::MyEventsBasedObject", "MyCustomObject", 1);
|
||||
}
|
||||
|
||||
@@ -1157,24 +1163,30 @@ SetupProjectWithEventsFunctionExtension(gd::Project &project) {
|
||||
externalEvents.SetAssociatedLayout("Scene");
|
||||
|
||||
// Objects with event based behaviors
|
||||
auto &object = layout.InsertNewObject(project, "MyExtension::Sprite",
|
||||
"ObjectWithMyBehavior", 0);
|
||||
object.AddNewBehavior(project, "MyEventsExtension::MyEventsBasedBehavior", "MyBehavior");
|
||||
auto &object = layout.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "ObjectWithMyBehavior", 0);
|
||||
object.AddNewBehavior(project, "MyEventsExtension::MyEventsBasedBehavior",
|
||||
"MyBehavior");
|
||||
object.GetVariables().InsertNew("MyVariable");
|
||||
object.GetVariables().InsertNew("MyStructureVariable").CastTo(gd::Variable::Structure);
|
||||
auto &group = layout.GetObjectGroups().InsertNew("GroupWithMyBehavior", 0);
|
||||
object.GetVariables()
|
||||
.InsertNew("MyStructureVariable")
|
||||
.CastTo(gd::Variable::Structure);
|
||||
auto &group = layout.GetObjects().GetObjectGroups().InsertNew(
|
||||
"GroupWithMyBehavior", 0);
|
||||
group.AddObject("ObjectWithMyBehavior");
|
||||
|
||||
auto &globalObject = project.InsertNewObject(
|
||||
auto &globalObject = project.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "GlobalObjectWithMyBehavior", 0);
|
||||
globalObject.AddNewBehavior(project, "MyEventsExtension::MyEventsBasedBehavior", "MyBehavior");
|
||||
globalObject.AddNewBehavior(
|
||||
project, "MyEventsExtension::MyEventsBasedBehavior", "MyBehavior");
|
||||
|
||||
// Custom objects
|
||||
layout.InsertNewObject(project, "MyEventsExtension::MyEventsBasedObject",
|
||||
"MyCustomObject", 1);
|
||||
layout.GetObjects().InsertNewObject(
|
||||
project, "MyEventsExtension::MyEventsBasedObject", "MyCustomObject", 1);
|
||||
|
||||
project.InsertNewObject(project, "MyEventsExtension::MyEventsBasedObject",
|
||||
"MyGlobalCustomObject", 1);
|
||||
project.GetObjects().InsertNewObject(
|
||||
project, "MyEventsExtension::MyEventsBasedObject",
|
||||
"MyGlobalCustomObject", 1);
|
||||
|
||||
SetupEvents(layout.GetEvents());
|
||||
SetupEvents(externalEvents.GetEvents());
|
||||
@@ -1209,19 +1221,24 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
|
||||
group1.AddObject("Object2");
|
||||
group1.AddObject("NotExistingObject");
|
||||
group1.AddObject("GlobalObject1");
|
||||
layout1.GetObjectGroups().Insert(group1);
|
||||
layout1.GetObjects().GetObjectGroups().Insert(group1);
|
||||
|
||||
layout1.InsertNewObject(project, "MyExtension::Sprite", "Object1", 0);
|
||||
layout1.InsertNewObject(project, "MyExtension::Sprite", "Object2", 0);
|
||||
layout1.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "Object1", 0);
|
||||
layout1.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "Object2", 0);
|
||||
|
||||
gd::WholeProjectRefactorer::ObjectRemovedInLayout(
|
||||
project, layout1, "Object1");
|
||||
gd::WholeProjectRefactorer::GlobalObjectRemoved(
|
||||
project, "GlobalObject1");
|
||||
REQUIRE(layout1.GetObjectGroups()[0].Find("Object1") == false);
|
||||
REQUIRE(layout1.GetObjectGroups()[0].Find("Object2") == true);
|
||||
REQUIRE(layout1.GetObjectGroups()[0].Find("NotExistingObject") == true);
|
||||
REQUIRE(layout1.GetObjectGroups()[0].Find("GlobalObject1") == false);
|
||||
gd::WholeProjectRefactorer::ObjectRemovedInLayout(project, layout1,
|
||||
"Object1");
|
||||
gd::WholeProjectRefactorer::GlobalObjectRemoved(project, "GlobalObject1");
|
||||
REQUIRE(layout1.GetObjects().GetObjectGroups()[0].Find(
|
||||
"Object1") == false);
|
||||
REQUIRE(layout1.GetObjects().GetObjectGroups()[0].Find(
|
||||
"Object2") == true);
|
||||
REQUIRE(layout1.GetObjects().GetObjectGroups()[0].Find(
|
||||
"NotExistingObject") == true);
|
||||
REQUIRE(layout1.GetObjects().GetObjectGroups()[0].Find(
|
||||
"GlobalObject1") == false);
|
||||
}
|
||||
|
||||
SECTION("Initial instances") {
|
||||
@@ -1230,8 +1247,10 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
auto &layout1 = project.InsertNewLayout("Layout1", 0);
|
||||
|
||||
layout1.InsertNewObject(project, "MyExtension::Sprite", "Object1", 0);
|
||||
layout1.InsertNewObject(project, "MyExtension::Sprite", "Object2", 0);
|
||||
layout1.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "Object1", 0);
|
||||
layout1.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "Object2", 0);
|
||||
|
||||
gd::InitialInstance instance1;
|
||||
instance1.SetObjectName("Object1");
|
||||
@@ -1269,8 +1288,10 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
|
||||
externalLayout1.SetAssociatedLayout("Layout1");
|
||||
externalLayout2.SetAssociatedLayout("Layout2");
|
||||
|
||||
layout1.InsertNewObject(project, "MyExtension::Sprite", "Object1", 0);
|
||||
layout1.InsertNewObject(project, "MyExtension::Sprite", "Object2", 0);
|
||||
layout1.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "Object1", 0);
|
||||
layout1.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "Object2", 0);
|
||||
|
||||
gd::InitialInstance instance1;
|
||||
instance1.SetObjectName("Object1");
|
||||
@@ -1316,20 +1337,27 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
|
||||
group1.AddObject("Object2");
|
||||
group1.AddObject("NotExistingObject");
|
||||
group1.AddObject("GlobalObject1");
|
||||
layout1.GetObjectGroups().Insert(group1);
|
||||
layout1.GetObjects().GetObjectGroups().Insert(group1);
|
||||
|
||||
layout1.InsertNewObject(project, "MyExtension::Sprite", "Object1", 0);
|
||||
layout1.InsertNewObject(project, "MyExtension::Sprite", "Object2", 0);
|
||||
layout1.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "Object1", 0);
|
||||
layout1.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "Object2", 0);
|
||||
|
||||
gd::WholeProjectRefactorer::ObjectOrGroupRenamedInLayout(
|
||||
project, layout1, "Object1", "Object3", /* isObjectGroup =*/false);
|
||||
gd::WholeProjectRefactorer::GlobalObjectOrGroupRenamed(
|
||||
project, "GlobalObject1", "GlobalObject3", /* isObjectGroup =*/false);
|
||||
REQUIRE(layout1.GetObjectGroups()[0].Find("Object1") == false);
|
||||
REQUIRE(layout1.GetObjectGroups()[0].Find("Object2") == true);
|
||||
REQUIRE(layout1.GetObjectGroups()[0].Find("Object3") == true);
|
||||
REQUIRE(layout1.GetObjectGroups()[0].Find("GlobalObject1") == false);
|
||||
REQUIRE(layout1.GetObjectGroups()[0].Find("GlobalObject3") == true);
|
||||
REQUIRE(layout1.GetObjects().GetObjectGroups()[0].Find(
|
||||
"Object1") == false);
|
||||
REQUIRE(layout1.GetObjects().GetObjectGroups()[0].Find(
|
||||
"Object2") == true);
|
||||
REQUIRE(layout1.GetObjects().GetObjectGroups()[0].Find(
|
||||
"Object3") == true);
|
||||
REQUIRE(layout1.GetObjects().GetObjectGroups()[0].Find(
|
||||
"GlobalObject1") == false);
|
||||
REQUIRE(layout1.GetObjects().GetObjectGroups()[0].Find(
|
||||
"GlobalObject3") == true);
|
||||
}
|
||||
|
||||
SECTION("Initial instances") {
|
||||
@@ -1338,8 +1366,10 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
auto &layout1 = project.InsertNewLayout("Layout1", 0);
|
||||
|
||||
layout1.InsertNewObject(project, "MyExtension::Sprite", "Object1", 0);
|
||||
layout1.InsertNewObject(project, "MyExtension::Sprite", "Object2", 0);
|
||||
layout1.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "Object1", 0);
|
||||
layout1.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "Object2", 0);
|
||||
|
||||
gd::InitialInstance instance1;
|
||||
instance1.SetObjectName("Object1");
|
||||
@@ -1379,8 +1409,10 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
|
||||
externalLayout1.SetAssociatedLayout("Layout1");
|
||||
externalLayout2.SetAssociatedLayout("Layout2");
|
||||
|
||||
layout1.InsertNewObject(project, "MyExtension::Sprite", "Object1", 0);
|
||||
layout1.InsertNewObject(project, "MyExtension::Sprite", "Object2", 0);
|
||||
layout1.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "Object1", 0);
|
||||
layout1.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "Object2", 0);
|
||||
|
||||
gd::InitialInstance instance1;
|
||||
instance1.SetObjectName("Object1");
|
||||
@@ -1481,8 +1513,8 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
|
||||
auto &scene = project.InsertNewLayout("Scene", 0);
|
||||
auto &object =
|
||||
scene.InsertNewObject(project, "MyExtension::Sprite", "Object", 0);
|
||||
auto &object = scene.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "Object", 0);
|
||||
|
||||
gd::StandardEvent &event =
|
||||
dynamic_cast<gd::StandardEvent &>(scene.GetEvents().InsertNewEvent(
|
||||
@@ -1529,16 +1561,15 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
|
||||
// events in this test.
|
||||
|
||||
// Create the objects container for the events function
|
||||
gd::ObjectsContainer globalObjectsContainer;
|
||||
gd::ObjectsContainer objectsContainer;
|
||||
gd::ParameterMetadataTools::ParametersToObjectsContainer(
|
||||
project, eventsFunction.GetParameters(), objectsContainer);
|
||||
// (this is strictly not necessary because we're not testing events in
|
||||
// this test)
|
||||
gd::ObjectsContainer parametersObjectsContainer;
|
||||
auto projectScopedContainers = gd::ProjectScopedContainers::
|
||||
MakeNewProjectScopedContainersForFreeEventsFunction(
|
||||
project, eventsExtension, eventsFunction,
|
||||
parametersObjectsContainer);
|
||||
|
||||
// Trigger the refactoring after the renaming of an object
|
||||
gd::WholeProjectRefactorer::ObjectOrGroupRenamedInEventsFunction(
|
||||
project, eventsFunction, globalObjectsContainer, objectsContainer,
|
||||
project, projectScopedContainers, eventsFunction,
|
||||
"Object1", "RenamedObject1",
|
||||
/* isObjectGroup=*/false);
|
||||
|
||||
@@ -1558,20 +1589,21 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
|
||||
eventsExtension.GetEventsFunction("MyOtherEventsFunction");
|
||||
|
||||
// Create the objects container for the events function
|
||||
gd::ObjectsContainer globalObjectsContainer;
|
||||
gd::ObjectsContainer objectsContainer;
|
||||
gd::ParameterMetadataTools::ParametersToObjectsContainer(
|
||||
project, eventsFunction.GetParameters(), objectsContainer);
|
||||
gd::ObjectsContainer parametersObjectsContainer;
|
||||
auto projectScopedContainers = gd::ProjectScopedContainers::
|
||||
MakeNewProjectScopedContainersForFreeEventsFunction(
|
||||
project, eventsExtension, eventsFunction,
|
||||
parametersObjectsContainer);
|
||||
|
||||
// Simulate a variable in ObjectWithMyBehavior, even if this is not
|
||||
// supported by the editor.
|
||||
auto& objectWithMyBehavior = objectsContainer.GetObject("ObjectWithMyBehavior");
|
||||
auto& objectWithMyBehavior = parametersObjectsContainer.GetObject("ObjectWithMyBehavior");
|
||||
objectWithMyBehavior.GetVariables().InsertNew("MyVariable");
|
||||
objectWithMyBehavior.GetVariables().InsertNew("MyStructureVariable").CastTo(gd::Variable::Structure);
|
||||
|
||||
// Trigger the refactoring after the renaming of an object
|
||||
gd::WholeProjectRefactorer::ObjectOrGroupRenamedInEventsFunction(
|
||||
project, eventsFunction, globalObjectsContainer, objectsContainer,
|
||||
project, projectScopedContainers, eventsFunction,
|
||||
"ObjectWithMyBehavior", "RenamedObjectWithMyBehavior",
|
||||
/* isObjectGroup=*/false);
|
||||
|
||||
@@ -1590,76 +1622,230 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
|
||||
}
|
||||
|
||||
SECTION("Object renamed (in events-based object)") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
auto &eventsExtension = SetupProjectWithEventsFunctionExtension(project);
|
||||
SECTION("Groups") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
auto &eventsExtension =
|
||||
project.InsertNewEventsFunctionsExtension("MyEventsExtension", 0);
|
||||
auto &eventsBasedObject =
|
||||
eventsExtension.GetEventsBasedObjects().InsertNew(
|
||||
"MyEventsBasedObject", 0);
|
||||
|
||||
auto &eventsBasedObject =
|
||||
project.GetEventsFunctionsExtension("MyEventsExtension")
|
||||
.GetEventsBasedObjects()
|
||||
.Get("MyOtherEventsBasedObject");
|
||||
gd::ObjectGroup group1;
|
||||
group1.AddObject("Object1");
|
||||
group1.AddObject("Object2");
|
||||
group1.AddObject("NotExistingObject");
|
||||
eventsBasedObject.GetObjects().GetObjectGroups().Insert(group1);
|
||||
|
||||
// Create the objects container for the events function
|
||||
gd::ObjectsContainer globalObjectsContainer;
|
||||
eventsBasedObject.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "Object1", 0);
|
||||
eventsBasedObject.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "Object2", 0);
|
||||
|
||||
// Trigger the refactoring after the renaming of an object
|
||||
gd::WholeProjectRefactorer::ObjectOrGroupRenamedInEventsBasedObject(
|
||||
project, globalObjectsContainer, eventsBasedObject,
|
||||
"ObjectWithMyBehavior", "RenamedObjectWithMyBehavior",
|
||||
/* isObjectGroup=*/false);
|
||||
// Create the objects container for the events function
|
||||
gd::ObjectsContainer parametersObjectsContainer;
|
||||
auto projectScopedContainers = gd::ProjectScopedContainers::
|
||||
MakeNewProjectScopedContainersForEventsBasedObject(
|
||||
project, eventsExtension, eventsBasedObject,
|
||||
parametersObjectsContainer);
|
||||
|
||||
auto &objectFunctionEvents =
|
||||
eventsBasedObject
|
||||
.GetEventsFunctions()
|
||||
.GetEventsFunction("MyObjectEventsFunction")
|
||||
.GetEvents();
|
||||
gd::WholeProjectRefactorer::ObjectOrGroupRenamedInEventsBasedObject(
|
||||
project, projectScopedContainers, eventsBasedObject, "Object1",
|
||||
"Object3", /* isObjectGroup =*/false);
|
||||
REQUIRE(eventsBasedObject.GetObjects().GetObjectGroups().size() == 1);
|
||||
REQUIRE(eventsBasedObject.GetObjects().GetObjectGroups()[0].Find(
|
||||
"Object1") == false);
|
||||
REQUIRE(eventsBasedObject.GetObjects().GetObjectGroups()[0].Find(
|
||||
"Object2") == true);
|
||||
REQUIRE(eventsBasedObject.GetObjects().GetObjectGroups()[0].Find(
|
||||
"Object3") == true);
|
||||
}
|
||||
|
||||
// Check object name has been renamed in action parameters.
|
||||
REQUIRE(GetEventFirstActionFirstParameterString(
|
||||
objectFunctionEvents.GetEvent(FreeFunctionWithObjects)) ==
|
||||
"RenamedObjectWithMyBehavior");
|
||||
SECTION("Initial instances") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
auto &eventsExtension =
|
||||
project.InsertNewEventsFunctionsExtension("MyEventsExtension", 0);
|
||||
auto &eventsBasedObject =
|
||||
eventsExtension.GetEventsBasedObjects().InsertNew(
|
||||
"MyEventsBasedObject", 0);
|
||||
|
||||
// Check object name has been renamed in expressions and object variables.
|
||||
REQUIRE(GetEventFirstActionFirstParameterString(
|
||||
objectFunctionEvents.GetEvent(FreeFunctionWithObjectExpression)) ==
|
||||
"RenamedObjectWithMyBehavior.GetObjectNumber() + RenamedObjectWithMyBehavior.MyVariable + RenamedObjectWithMyBehavior.MyStructureVariable.Child");
|
||||
eventsBasedObject.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "Object1", 0);
|
||||
eventsBasedObject.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "Object2", 0);
|
||||
|
||||
gd::InitialInstance instance1;
|
||||
instance1.SetObjectName("Object1");
|
||||
gd::InitialInstance instance2;
|
||||
instance2.SetObjectName("Object2");
|
||||
eventsBasedObject.GetInitialInstances().InsertInitialInstance(instance1);
|
||||
eventsBasedObject.GetInitialInstances().InsertInitialInstance(instance2);
|
||||
|
||||
// Create the objects container for the events function
|
||||
gd::ObjectsContainer parametersObjectsContainer;
|
||||
auto projectScopedContainers = gd::ProjectScopedContainers::
|
||||
MakeNewProjectScopedContainersForEventsBasedObject(
|
||||
project, eventsExtension, eventsBasedObject,
|
||||
parametersObjectsContainer);
|
||||
|
||||
gd::WholeProjectRefactorer::ObjectOrGroupRenamedInEventsBasedObject(
|
||||
project, projectScopedContainers, eventsBasedObject, "Object1",
|
||||
"Object3", /* isObjectGroup =*/false);
|
||||
REQUIRE(eventsBasedObject.GetInitialInstances().HasInstancesOfObject(
|
||||
"Object1") == false);
|
||||
REQUIRE(eventsBasedObject.GetInitialInstances().HasInstancesOfObject(
|
||||
"Object3") == true);
|
||||
}
|
||||
|
||||
SECTION("Events") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
auto &eventsExtension = SetupProjectWithEventsFunctionExtension(project);
|
||||
auto &eventsBasedObject =
|
||||
project.GetEventsFunctionsExtension("MyEventsExtension")
|
||||
.GetEventsBasedObjects()
|
||||
.Get("MyOtherEventsBasedObject");
|
||||
|
||||
// Create the objects container for the events function
|
||||
gd::ObjectsContainer parametersObjectsContainer;
|
||||
auto projectScopedContainers = gd::ProjectScopedContainers::
|
||||
MakeNewProjectScopedContainersForEventsBasedObject(
|
||||
project, eventsExtension, eventsBasedObject,
|
||||
parametersObjectsContainer);
|
||||
|
||||
// Trigger the refactoring after the renaming of an object
|
||||
gd::WholeProjectRefactorer::ObjectOrGroupRenamedInEventsBasedObject(
|
||||
project, projectScopedContainers, eventsBasedObject,
|
||||
"ObjectWithMyBehavior", "RenamedObjectWithMyBehavior",
|
||||
/* isObjectGroup=*/false);
|
||||
|
||||
auto &objectFunctionEvents =
|
||||
eventsBasedObject.GetEventsFunctions()
|
||||
.GetEventsFunction("MyObjectEventsFunction")
|
||||
.GetEvents();
|
||||
|
||||
// Check object name has been renamed in action parameters.
|
||||
REQUIRE(GetEventFirstActionFirstParameterString(
|
||||
objectFunctionEvents.GetEvent(FreeFunctionWithObjects)) ==
|
||||
"RenamedObjectWithMyBehavior");
|
||||
|
||||
// Check object name has been renamed in expressions and object variables.
|
||||
REQUIRE(
|
||||
GetEventFirstActionFirstParameterString(objectFunctionEvents.GetEvent(
|
||||
FreeFunctionWithObjectExpression)) ==
|
||||
"RenamedObjectWithMyBehavior.GetObjectNumber() + "
|
||||
"RenamedObjectWithMyBehavior.MyVariable + "
|
||||
"RenamedObjectWithMyBehavior.MyStructureVariable.Child");
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Object deleted (in events function)") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
auto &eventsExtension =
|
||||
project.InsertNewEventsFunctionsExtension("MyEventsExtension", 0);
|
||||
SECTION("Object deleted (in events-based object)") {
|
||||
SECTION("Groups") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
auto &eventsExtension =
|
||||
project.InsertNewEventsFunctionsExtension("MyEventsExtension", 0);
|
||||
auto &eventsBasedObject =
|
||||
eventsExtension.GetEventsBasedObjects().InsertNew(
|
||||
"MyEventsBasedObject", 0);
|
||||
|
||||
// Add a (free) function with an object group
|
||||
gd::EventsFunction &eventsFunction =
|
||||
eventsExtension.InsertNewEventsFunction("MyEventsFunction", 0);
|
||||
gd::ObjectGroup &objectGroup =
|
||||
eventsFunction.GetObjectGroups().InsertNew("MyGroup", 0);
|
||||
objectGroup.AddObject("Object1");
|
||||
objectGroup.AddObject("Object2");
|
||||
// In theory, we would add the object parameters, but we're not testing
|
||||
// events in this test.
|
||||
gd::ObjectGroup group1;
|
||||
group1.AddObject("Object1");
|
||||
group1.AddObject("Object2");
|
||||
group1.AddObject("NotExistingObject");
|
||||
eventsBasedObject.GetObjects().GetObjectGroups().Insert(group1);
|
||||
|
||||
// Create the objects container for the events function
|
||||
gd::ObjectsContainer globalObjectsContainer;
|
||||
gd::ObjectsContainer objectsContainer;
|
||||
gd::ParameterMetadataTools::ParametersToObjectsContainer(
|
||||
project, eventsFunction.GetParameters(), objectsContainer);
|
||||
// (this is strictly not necessary because we're not testing events in this
|
||||
// test)
|
||||
eventsBasedObject.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "Object1", 0);
|
||||
eventsBasedObject.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "Object2", 0);
|
||||
|
||||
// Trigger the refactoring after the renaming of an object
|
||||
gd::WholeProjectRefactorer::ObjectRemovedInEventsFunction(
|
||||
project, eventsFunction, globalObjectsContainer, objectsContainer,
|
||||
"Object1");
|
||||
// Create the objects container for the events function
|
||||
gd::ObjectsContainer parametersObjectsContainer;
|
||||
auto projectScopedContainers = gd::ProjectScopedContainers::
|
||||
MakeNewProjectScopedContainersForEventsBasedObject(
|
||||
project, eventsExtension, eventsBasedObject,
|
||||
parametersObjectsContainer);
|
||||
|
||||
REQUIRE(objectGroup.Find("Object1") == false);
|
||||
REQUIRE(objectGroup.Find("Object2") == true);
|
||||
gd::WholeProjectRefactorer::ObjectRemovedInEventsBasedObject(
|
||||
project, eventsBasedObject, "Object1");
|
||||
REQUIRE(eventsBasedObject.GetObjects().GetObjectGroups().size() == 1);
|
||||
REQUIRE(eventsBasedObject.GetObjects().GetObjectGroups()[0].Find(
|
||||
"Object1") == false);
|
||||
REQUIRE(eventsBasedObject.GetObjects().GetObjectGroups()[0].Find(
|
||||
"Object2") == true);
|
||||
REQUIRE(eventsBasedObject.GetObjects().GetObjectGroups()[0].Find(
|
||||
"NotExistingObject") == true);
|
||||
}
|
||||
|
||||
// Events are not tested
|
||||
SECTION("Initial instances") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
auto &eventsExtension =
|
||||
project.InsertNewEventsFunctionsExtension("MyEventsExtension", 0);
|
||||
auto &eventsBasedObject =
|
||||
eventsExtension.GetEventsBasedObjects().InsertNew(
|
||||
"MyEventsBasedObject", 0);
|
||||
|
||||
eventsBasedObject.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "Object1", 0);
|
||||
eventsBasedObject.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "Object2", 0);
|
||||
|
||||
gd::InitialInstance instance1;
|
||||
instance1.SetObjectName("Object1");
|
||||
gd::InitialInstance instance2;
|
||||
instance2.SetObjectName("Object2");
|
||||
eventsBasedObject.GetInitialInstances().InsertInitialInstance(instance1);
|
||||
eventsBasedObject.GetInitialInstances().InsertInitialInstance(instance2);
|
||||
|
||||
// Create the objects container for the events function
|
||||
gd::ObjectsContainer parametersObjectsContainer;
|
||||
auto projectScopedContainers = gd::ProjectScopedContainers::
|
||||
MakeNewProjectScopedContainersForEventsBasedObject(
|
||||
project, eventsExtension, eventsBasedObject,
|
||||
parametersObjectsContainer);
|
||||
|
||||
gd::WholeProjectRefactorer::ObjectRemovedInEventsBasedObject(
|
||||
project, eventsBasedObject, "Object1");
|
||||
REQUIRE(eventsBasedObject.GetInitialInstances().HasInstancesOfObject(
|
||||
"Object1") == false);
|
||||
REQUIRE(eventsBasedObject.GetInitialInstances().HasInstancesOfObject(
|
||||
"Object2") == true);
|
||||
}
|
||||
|
||||
SECTION("Function groups") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
auto &eventsExtension =
|
||||
project.InsertNewEventsFunctionsExtension("MyEventsExtension", 0);
|
||||
|
||||
// Add a (free) function with an object group
|
||||
gd::EventsFunction &eventsFunction =
|
||||
eventsExtension.InsertNewEventsFunction("MyEventsFunction", 0);
|
||||
gd::ObjectGroup &objectGroup =
|
||||
eventsFunction.GetObjectGroups().InsertNew("MyGroup", 0);
|
||||
objectGroup.AddObject("Object1");
|
||||
objectGroup.AddObject("Object2");
|
||||
// In theory, we would add the object parameters, but we're not testing
|
||||
// events in this test.
|
||||
|
||||
// Trigger the refactoring after the renaming of an object
|
||||
gd::WholeProjectRefactorer::ObjectRemovedInEventsFunction(
|
||||
project, eventsFunction, "Object1");
|
||||
|
||||
REQUIRE(objectGroup.Find("Object1") == false);
|
||||
REQUIRE(objectGroup.Find("Object2") == true);
|
||||
|
||||
// Events are not tested
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Events extension renamed in instructions") {
|
||||
@@ -1700,31 +1886,37 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
|
||||
// Check that the type of the behavior was changed in the behaviors of
|
||||
// objects. Name is *not* changed.
|
||||
REQUIRE(project.GetLayout("Scene")
|
||||
.GetObjects()
|
||||
.GetObject("ObjectWithMyBehavior")
|
||||
.GetBehavior("MyBehavior")
|
||||
.GetTypeName() ==
|
||||
"MyRenamedExtension::MyEventsBasedBehavior");
|
||||
REQUIRE(project.GetObject("GlobalObjectWithMyBehavior")
|
||||
REQUIRE(project.GetObjects()
|
||||
.GetObject("GlobalObjectWithMyBehavior")
|
||||
.GetBehavior("MyBehavior")
|
||||
.GetTypeName() ==
|
||||
"MyRenamedExtension::MyEventsBasedBehavior");
|
||||
REQUIRE(project.GetEventsFunctionsExtension("MyEventsExtension")
|
||||
.GetEventsBasedObjects()
|
||||
.Get("MyOtherEventsBasedObject")
|
||||
.GetObjects()
|
||||
.GetObject("ObjectWithMyBehavior")
|
||||
.GetBehavior("MyBehavior")
|
||||
.GetTypeName() ==
|
||||
"MyRenamedExtension::MyEventsBasedBehavior");
|
||||
|
||||
// Check that the type of the object was changed. Name is *not* changed.
|
||||
REQUIRE(
|
||||
project.GetLayout("Scene").GetObject("MyCustomObject").GetType() ==
|
||||
"MyRenamedExtension::MyEventsBasedObject");
|
||||
REQUIRE(project.GetObject("MyGlobalCustomObject").GetType() ==
|
||||
"MyRenamedExtension::MyEventsBasedObject");
|
||||
REQUIRE(project.GetLayout("Scene")
|
||||
.GetObjects()
|
||||
.GetObject("MyCustomObject")
|
||||
.GetType() == "MyRenamedExtension::MyEventsBasedObject");
|
||||
REQUIRE(project.GetObjects()
|
||||
.GetObject("MyGlobalCustomObject")
|
||||
.GetType() == "MyRenamedExtension::MyEventsBasedObject");
|
||||
REQUIRE(project.GetEventsFunctionsExtension("MyEventsExtension")
|
||||
.GetEventsBasedObjects()
|
||||
.Get("MyOtherEventsBasedObject")
|
||||
.GetObjects()
|
||||
.GetObject("MyCustomObject")
|
||||
.GetType() == "MyRenamedExtension::MyEventsBasedObject");
|
||||
|
||||
@@ -1774,11 +1966,13 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
|
||||
|
||||
// Check that the type of the object was changed in the custom
|
||||
// objects. Name is *not* changed.
|
||||
REQUIRE(
|
||||
project.GetLayout("Scene").GetObject("MyCustomObject").GetType() ==
|
||||
"MyRenamedExtension::MyEventsBasedObject");
|
||||
REQUIRE(project.GetObject("MyGlobalCustomObject").GetType() ==
|
||||
"MyRenamedExtension::MyEventsBasedObject");
|
||||
REQUIRE(project.GetLayout("Scene")
|
||||
.GetObjects()
|
||||
.GetObject("MyCustomObject")
|
||||
.GetType() == "MyRenamedExtension::MyEventsBasedObject");
|
||||
REQUIRE(project.GetObjects()
|
||||
.GetObject("MyGlobalCustomObject")
|
||||
.GetType() == "MyRenamedExtension::MyEventsBasedObject");
|
||||
|
||||
// Check if events-based object methods have been renamed in
|
||||
// instructions
|
||||
@@ -2075,17 +2269,20 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
|
||||
// Check that the type of the behavior was changed in the behaviors of
|
||||
// objects. Name is *not* changed.
|
||||
REQUIRE(project.GetLayout("Scene")
|
||||
.GetObjects()
|
||||
.GetObject("ObjectWithMyBehavior")
|
||||
.GetBehavior("MyBehavior")
|
||||
.GetTypeName() ==
|
||||
"MyEventsExtension::MyRenamedEventsBasedBehavior");
|
||||
REQUIRE(project.GetObject("GlobalObjectWithMyBehavior")
|
||||
REQUIRE(project.GetObjects()
|
||||
.GetObject("GlobalObjectWithMyBehavior")
|
||||
.GetBehavior("MyBehavior")
|
||||
.GetTypeName() ==
|
||||
"MyEventsExtension::MyRenamedEventsBasedBehavior");
|
||||
REQUIRE(project.GetEventsFunctionsExtension("MyEventsExtension")
|
||||
.GetEventsBasedObjects()
|
||||
.Get("MyOtherEventsBasedObject")
|
||||
.GetObjects()
|
||||
.GetObject("ObjectWithMyBehavior")
|
||||
.GetBehavior("MyBehavior")
|
||||
.GetTypeName() ==
|
||||
@@ -2187,13 +2384,17 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
|
||||
"MyRenamedEventsBasedObject");
|
||||
|
||||
// Check that the type of the object was changed. Name is *not* changed.
|
||||
REQUIRE(project.GetLayout("Scene").GetObject("MyCustomObject").GetType() ==
|
||||
"MyEventsExtension::MyRenamedEventsBasedObject");
|
||||
REQUIRE(project.GetObject("MyGlobalCustomObject").GetType() ==
|
||||
"MyEventsExtension::MyRenamedEventsBasedObject");
|
||||
REQUIRE(project.GetLayout("Scene")
|
||||
.GetObjects()
|
||||
.GetObject("MyCustomObject")
|
||||
.GetType() == "MyEventsExtension::MyRenamedEventsBasedObject");
|
||||
REQUIRE(project.GetObjects()
|
||||
.GetObject("MyGlobalCustomObject")
|
||||
.GetType() == "MyEventsExtension::MyRenamedEventsBasedObject");
|
||||
REQUIRE(project.GetEventsFunctionsExtension("MyEventsExtension")
|
||||
.GetEventsBasedObjects()
|
||||
.Get("MyOtherEventsBasedObject")
|
||||
.GetObjects()
|
||||
.GetObject("MyCustomObject")
|
||||
.GetType() == "MyEventsExtension::MyRenamedEventsBasedObject");
|
||||
|
||||
@@ -2844,8 +3045,8 @@ TEST_CASE("WholeProjectRefactorer (FindInvalidRequiredBehaviorProperties)",
|
||||
|
||||
// Insert an object using a behavior requiring another behavior.
|
||||
// But don't fill the property, which is a problem.
|
||||
auto &object =
|
||||
project.InsertNewObject(project, "MyExtension::Sprite", "MyObject", 0);
|
||||
auto &object = project.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "MyObject", 0);
|
||||
object.AddNewBehavior(project,
|
||||
"MyExtension::BehaviorWithRequiredBehaviorProperty",
|
||||
"MyBehaviorWithRequiredBehaviorProperty");
|
||||
@@ -2867,8 +3068,8 @@ TEST_CASE("WholeProjectRefactorer (FindInvalidRequiredBehaviorProperties)",
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
|
||||
// Insert an object using a behavior requiring another behavior.
|
||||
auto &object =
|
||||
project.InsertNewObject(project, "MyExtension::Sprite", "MyObject", 0);
|
||||
auto &object = project.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "MyObject", 0);
|
||||
object.AddNewBehavior(project,
|
||||
"MyExtension::BehaviorWithRequiredBehaviorProperty",
|
||||
"MyBehaviorWithRequiredBehaviorProperty");
|
||||
@@ -2891,8 +3092,8 @@ TEST_CASE("WholeProjectRefactorer (FindInvalidRequiredBehaviorProperties)",
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
|
||||
// Insert an object using a behavior requiring another behavior.
|
||||
auto &object =
|
||||
project.InsertNewObject(project, "MyExtension::Sprite", "MyObject", 0);
|
||||
auto &object = project.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "MyObject", 0);
|
||||
object.AddNewBehavior(project,
|
||||
"MyExtension::BehaviorWithRequiredBehaviorProperty",
|
||||
"MyBehaviorWithRequiredBehaviorProperty");
|
||||
@@ -2923,8 +3124,8 @@ TEST_CASE("WholeProjectRefactorer (FindInvalidRequiredBehaviorProperties)",
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
|
||||
// Insert an object using a behavior requiring another behavior.
|
||||
auto &object =
|
||||
project.InsertNewObject(project, "MyExtension::Sprite", "MyObject", 0);
|
||||
auto &object = project.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "MyObject", 0);
|
||||
object.AddNewBehavior(project,
|
||||
"MyExtension::BehaviorWithRequiredBehaviorProperty",
|
||||
"MyBehaviorWithRequiredBehaviorProperty");
|
||||
@@ -2974,8 +3175,8 @@ TEST_CASE("WholeProjectRefactorer (FixInvalidRequiredBehaviorProperties)",
|
||||
|
||||
// Insert an object using a behavior requiring another behavior.
|
||||
// But don't fill the property, which is a problem.
|
||||
auto &object =
|
||||
project.InsertNewObject(project, "MyExtension::Sprite", "MyObject", 0);
|
||||
auto &object = project.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "MyObject", 0);
|
||||
object.AddNewBehavior(project,
|
||||
"MyExtension::BehaviorWithRequiredBehaviorProperty",
|
||||
"MyBehaviorWithRequiredBehaviorProperty");
|
||||
@@ -3014,8 +3215,8 @@ TEST_CASE("WholeProjectRefactorer (FixInvalidRequiredBehaviorProperties)",
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
|
||||
// Insert an object using a behavior requiring another behavior.
|
||||
auto &object =
|
||||
project.InsertNewObject(project, "MyExtension::Sprite", "MyObject", 0);
|
||||
auto &object = project.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "MyObject", 0);
|
||||
object.AddNewBehavior(project,
|
||||
"MyExtension::BehaviorWithRequiredBehaviorProperty",
|
||||
"MyBehaviorWithRequiredBehaviorProperty");
|
||||
@@ -3057,8 +3258,8 @@ TEST_CASE("WholeProjectRefactorer (AddBehaviorAndRequiredBehaviors)",
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
auto &object =
|
||||
project.InsertNewObject(project, "MyExtension::Sprite", "MyObject", 0);
|
||||
auto &object = project.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "MyObject", 0);
|
||||
|
||||
// Add a simple behavior.
|
||||
gd::WholeProjectRefactorer::AddBehaviorAndRequiredBehaviors(
|
||||
@@ -3072,8 +3273,8 @@ TEST_CASE("WholeProjectRefactorer (AddBehaviorAndRequiredBehaviors)",
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
auto &object =
|
||||
project.InsertNewObject(project, "MyExtension::Sprite", "MyObject", 0);
|
||||
auto &object = project.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "MyObject", 0);
|
||||
|
||||
// Add an unknown behavior.
|
||||
gd::WholeProjectRefactorer::AddBehaviorAndRequiredBehaviors(
|
||||
@@ -3088,8 +3289,8 @@ TEST_CASE("WholeProjectRefactorer (AddBehaviorAndRequiredBehaviors)",
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
auto &object =
|
||||
project.InsertNewObject(project, "MyExtension::Sprite", "MyObject", 0);
|
||||
auto &object = project.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "MyObject", 0);
|
||||
|
||||
// Add the behavior that requires a behavior.
|
||||
gd::WholeProjectRefactorer::AddBehaviorAndRequiredBehaviors(
|
||||
@@ -3118,8 +3319,8 @@ TEST_CASE("WholeProjectRefactorer (AddBehaviorAndRequiredBehaviors)",
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
auto &object =
|
||||
project.InsertNewObject(project, "MyExtension::Sprite", "MyObject", 0);
|
||||
auto &object = project.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "MyObject", 0);
|
||||
|
||||
// Add the behavior that requires a behavior that requires another.
|
||||
gd::WholeProjectRefactorer::AddBehaviorAndRequiredBehaviors(
|
||||
@@ -3161,8 +3362,8 @@ TEST_CASE("WholeProjectRefactorer (FindDependentBehaviorNames)", "[common]") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
auto &object =
|
||||
project.InsertNewObject(project, "MyExtension::Sprite", "MyObject", 0);
|
||||
auto &object = project.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "MyObject", 0);
|
||||
|
||||
// Add the behavior that requires a behavior that requires another.
|
||||
gd::WholeProjectRefactorer::AddBehaviorAndRequiredBehaviors(
|
||||
@@ -3213,8 +3414,8 @@ TEST_CASE("WholeProjectRefactorer (FindDependentBehaviorNames failing cases)",
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
auto &object =
|
||||
project.InsertNewObject(project, "MyExtension::Sprite", "MyObject", 0);
|
||||
auto &object = project.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "MyObject", 0);
|
||||
|
||||
// Add the behavior that requires a behavior that requires another.
|
||||
gd::WholeProjectRefactorer::AddBehaviorAndRequiredBehaviors(
|
||||
@@ -3625,9 +3826,12 @@ TEST_CASE("RenameObjectAnimation", "[common]") {
|
||||
auto &otherExternalEvents =
|
||||
project.InsertNewExternalEvents("My external events", 0);
|
||||
otherExternalEvents.SetAssociatedLayout("My other layout");
|
||||
auto &object = layout.InsertNewObject(project, "MyExtension::Sprite", "MySprite", 0);
|
||||
layout.InsertNewObject(project, "MyExtension::Sprite", "MySprite2", 1);
|
||||
otherLayout.InsertNewObject(project, "MyExtension::Sprite", "MySprite", 0);
|
||||
auto &object = layout.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "MySprite", 0);
|
||||
layout.GetObjects().InsertNewObject(project, "MyExtension::Sprite",
|
||||
"MySprite2", 1);
|
||||
otherLayout.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "MySprite", 0);
|
||||
|
||||
auto &layoutAction =
|
||||
CreateActionWithAnimationParameter(project, layout.GetEvents(), "MySprite");
|
||||
@@ -3733,9 +3937,12 @@ TEST_CASE("RenameLayerEffect", "[common]") {
|
||||
auto &otherExternalEvents =
|
||||
project.InsertNewExternalEvents("My external events", 0);
|
||||
otherExternalEvents.SetAssociatedLayout("My other layout");
|
||||
auto &object = layout.InsertNewObject(project, "MyExtension::Sprite", "MySprite", 0);
|
||||
layout.InsertNewObject(project, "MyExtension::Sprite", "MySprite2", 1);
|
||||
otherLayout.InsertNewObject(project, "MyExtension::Sprite", "MySprite", 0);
|
||||
auto &object = layout.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "MySprite", 0);
|
||||
layout.GetObjects().InsertNewObject(project, "MyExtension::Sprite",
|
||||
"MySprite2", 1);
|
||||
otherLayout.GetObjects().InsertNewObject(
|
||||
project, "MyExtension::Sprite", "MySprite", 0);
|
||||
|
||||
auto &layoutAction =
|
||||
CreateActionWithLayerEffectParameter(project, layout.GetEvents(), "My layer");
|
||||
@@ -3794,7 +4001,7 @@ TEST_CASE("RenameLayerEffect", "[common]") {
|
||||
}
|
||||
|
||||
TEST_CASE("RemoveLayer", "[common]") {
|
||||
SECTION("Can remove instances in a layout and its associated external layouts") {
|
||||
SECTION("Can remove instances from a layer (in a scene and their associated external layouts)") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
@@ -3838,7 +4045,7 @@ TEST_CASE("RemoveLayer", "[common]") {
|
||||
REQUIRE(initialInstances.GetLayerInstancesCount("My layer") == 3);
|
||||
REQUIRE(externalInitialInstances.GetLayerInstancesCount("My layer") == 2);
|
||||
|
||||
gd::WholeProjectRefactorer::RemoveLayer(project, layout, "My layer");
|
||||
gd::WholeProjectRefactorer::RemoveLayerInScene(project, layout, "My layer");
|
||||
|
||||
REQUIRE(initialInstances.GetInstancesCount() == 2);
|
||||
REQUIRE(externalInitialInstances.GetInstancesCount() == 1);
|
||||
@@ -3848,10 +4055,38 @@ TEST_CASE("RemoveLayer", "[common]") {
|
||||
REQUIRE(initialInstances.GetLayerInstancesCount("My layer") == 0);
|
||||
REQUIRE(externalInitialInstances.GetLayerInstancesCount("My layer") == 0);
|
||||
}
|
||||
|
||||
SECTION("Can remove instances from a layer (in an events-based object)") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
|
||||
auto &eventsExtension =
|
||||
project.InsertNewEventsFunctionsExtension("MyEventsExtension", 0);
|
||||
auto &eventsBasedObject = eventsExtension.GetEventsBasedObjects().InsertNew(
|
||||
"MyEventsBasedObject", 0);
|
||||
eventsBasedObject.GetLayers().InsertNewLayer("My layer", 0);
|
||||
|
||||
auto &initialInstances = eventsBasedObject.GetInitialInstances();
|
||||
initialInstances.InsertNewInitialInstance().SetLayer("My layer");
|
||||
initialInstances.InsertNewInitialInstance().SetLayer("My layer");
|
||||
initialInstances.InsertNewInitialInstance().SetLayer("My layer");
|
||||
initialInstances.InsertNewInitialInstance().SetLayer("");
|
||||
initialInstances.InsertNewInitialInstance().SetLayer("");
|
||||
|
||||
REQUIRE(initialInstances.GetInstancesCount() == 5);
|
||||
REQUIRE(initialInstances.GetLayerInstancesCount("My layer") == 3);
|
||||
|
||||
gd::WholeProjectRefactorer::RemoveLayerInEventsBasedObject(
|
||||
eventsBasedObject, "My layer");
|
||||
|
||||
REQUIRE(initialInstances.GetInstancesCount() == 2);
|
||||
REQUIRE(initialInstances.GetLayerInstancesCount("My layer") == 0);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("MergeLayers", "[common]") {
|
||||
SECTION("Can merge instances from a layout into another layout (and their associated external layouts)") {
|
||||
SECTION("Can merge instances from a layer into another layer (in a scene and their associated external layouts)") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
@@ -3897,7 +4132,7 @@ TEST_CASE("MergeLayers", "[common]") {
|
||||
REQUIRE(initialInstances.GetLayerInstancesCount("My layer") == 3);
|
||||
REQUIRE(externalInitialInstances.GetLayerInstancesCount("My layer") == 2);
|
||||
|
||||
gd::WholeProjectRefactorer::MergeLayers(project, layout, "My layer", "");
|
||||
gd::WholeProjectRefactorer::MergeLayersInScene(project, layout, "My layer", "");
|
||||
|
||||
// No instance was removed.
|
||||
REQUIRE(initialInstances.GetInstancesCount() == 6);
|
||||
@@ -3917,4 +4152,39 @@ TEST_CASE("MergeLayers", "[common]") {
|
||||
REQUIRE(initialInstances.GetLayerInstancesCount("My other layer") == 1);
|
||||
REQUIRE(externalInitialInstances.GetLayerInstancesCount("My other layer") == 1);
|
||||
}
|
||||
|
||||
SECTION("Can merge instances from a layer into another layer (in an events-based object)") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
|
||||
auto &eventsExtension =
|
||||
project.InsertNewEventsFunctionsExtension("MyEventsExtension", 0);
|
||||
auto &eventsBasedObject = eventsExtension.GetEventsBasedObjects().InsertNew(
|
||||
"MyEventsBasedObject", 0);
|
||||
eventsBasedObject.GetLayers().InsertNewLayer("My layer", 0);
|
||||
|
||||
auto &initialInstances = eventsBasedObject.GetInitialInstances();
|
||||
initialInstances.InsertNewInitialInstance().SetLayer("My layer");
|
||||
initialInstances.InsertNewInitialInstance().SetLayer("My layer");
|
||||
initialInstances.InsertNewInitialInstance().SetLayer("My layer");
|
||||
initialInstances.InsertNewInitialInstance().SetLayer("");
|
||||
initialInstances.InsertNewInitialInstance().SetLayer("");
|
||||
initialInstances.InsertNewInitialInstance().SetLayer("My other layer");
|
||||
|
||||
REQUIRE(initialInstances.GetInstancesCount() == 6);
|
||||
REQUIRE(initialInstances.GetLayerInstancesCount("My layer") == 3);
|
||||
|
||||
gd::WholeProjectRefactorer::MergeLayersInEventsBasedObject(
|
||||
eventsBasedObject, "My layer", "");
|
||||
|
||||
// No instance was removed.
|
||||
REQUIRE(initialInstances.GetInstancesCount() == 6);
|
||||
|
||||
// No instance remain in "My layer".
|
||||
REQUIRE(initialInstances.GetLayerInstancesCount("My layer") == 0);
|
||||
|
||||
// Other layers from the same layout are untouched.
|
||||
REQUIRE(initialInstances.GetLayerInstancesCount("My other layer") == 1);
|
||||
}
|
||||
}
|
||||
|
@@ -1094,19 +1094,12 @@ module.exports = {
|
||||
objectContent,
|
||||
instance,
|
||||
propertyName,
|
||||
newValue,
|
||||
project,
|
||||
layout
|
||||
newValue
|
||||
) {
|
||||
return false;
|
||||
};
|
||||
|
||||
Cube3DObject.getInitialInstanceProperties = function (
|
||||
content,
|
||||
instance,
|
||||
project,
|
||||
layout
|
||||
) {
|
||||
Cube3DObject.getInitialInstanceProperties = function (content, instance) {
|
||||
const instanceProperties = new gd.MapStringPropertyDescriptor();
|
||||
return instanceProperties;
|
||||
};
|
||||
@@ -2115,7 +2108,6 @@ module.exports = {
|
||||
|
||||
constructor(
|
||||
project,
|
||||
layout,
|
||||
instance,
|
||||
associatedObjectConfiguration,
|
||||
pixiContainer,
|
||||
@@ -2123,7 +2115,6 @@ module.exports = {
|
||||
) {
|
||||
super(
|
||||
project,
|
||||
layout,
|
||||
instance,
|
||||
associatedObjectConfiguration,
|
||||
pixiContainer,
|
||||
@@ -2300,7 +2291,6 @@ module.exports = {
|
||||
class RenderedCube3DObject3DInstance extends Rendered3DInstance {
|
||||
constructor(
|
||||
project,
|
||||
layout,
|
||||
instance,
|
||||
associatedObjectConfiguration,
|
||||
pixiContainer,
|
||||
@@ -2309,7 +2299,6 @@ module.exports = {
|
||||
) {
|
||||
super(
|
||||
project,
|
||||
layout,
|
||||
instance,
|
||||
associatedObjectConfiguration,
|
||||
pixiContainer,
|
||||
@@ -2682,7 +2671,6 @@ module.exports = {
|
||||
|
||||
constructor(
|
||||
project,
|
||||
layout,
|
||||
instance,
|
||||
associatedObjectConfiguration,
|
||||
pixiContainer,
|
||||
@@ -2690,7 +2678,6 @@ module.exports = {
|
||||
) {
|
||||
super(
|
||||
project,
|
||||
layout,
|
||||
instance,
|
||||
associatedObjectConfiguration,
|
||||
pixiContainer,
|
||||
@@ -2945,7 +2932,6 @@ module.exports = {
|
||||
|
||||
constructor(
|
||||
project,
|
||||
layout,
|
||||
instance,
|
||||
associatedObjectConfiguration,
|
||||
pixiContainer,
|
||||
@@ -2954,7 +2940,6 @@ module.exports = {
|
||||
) {
|
||||
super(
|
||||
project,
|
||||
layout,
|
||||
instance,
|
||||
associatedObjectConfiguration,
|
||||
pixiContainer,
|
||||
|
@@ -165,14 +165,13 @@ Model3DObjectConfiguration::GetProperties() const {
|
||||
|
||||
bool Model3DObjectConfiguration::UpdateInitialInstanceProperty(
|
||||
gd::InitialInstance &instance, const gd::String &propertyName,
|
||||
const gd::String &newValue, gd::Project &project, gd::Layout &layout) {
|
||||
const gd::String &newValue) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::map<gd::String, gd::PropertyDescriptor>
|
||||
Model3DObjectConfiguration::GetInitialInstanceProperties(
|
||||
const gd::InitialInstance &instance, gd::Project &project,
|
||||
gd::Layout &layout) {
|
||||
const gd::InitialInstance &instance) {
|
||||
std::map<gd::String, gd::PropertyDescriptor> instanceProperties;
|
||||
return instanceProperties;
|
||||
}
|
||||
|
@@ -75,15 +75,11 @@ public:
|
||||
const gd::String &value) override;
|
||||
|
||||
virtual std::map<gd::String, gd::PropertyDescriptor>
|
||||
GetInitialInstanceProperties(const gd::InitialInstance &instance,
|
||||
gd::Project &project,
|
||||
gd::Layout &layout) override;
|
||||
GetInitialInstanceProperties(const gd::InitialInstance &instance) override;
|
||||
|
||||
virtual bool UpdateInitialInstanceProperty(gd::InitialInstance &instance,
|
||||
const gd::String &name,
|
||||
const gd::String &value,
|
||||
gd::Project &project,
|
||||
gd::Layout &layout) override;
|
||||
const gd::String &value) override;
|
||||
|
||||
/** \name Animations
|
||||
* Methods related to animations management
|
||||
|
@@ -132,18 +132,11 @@ module.exports = {
|
||||
objectContent,
|
||||
instance,
|
||||
propertyName,
|
||||
newValue,
|
||||
project,
|
||||
layout
|
||||
newValue
|
||||
) {
|
||||
return false;
|
||||
};
|
||||
objectBBText.getInitialInstanceProperties = function (
|
||||
content,
|
||||
instance,
|
||||
project,
|
||||
layout
|
||||
) {
|
||||
objectBBText.getInitialInstanceProperties = function (content, instance) {
|
||||
var instanceProperties = new gd.MapStringPropertyDescriptor();
|
||||
return instanceProperties;
|
||||
};
|
||||
@@ -500,7 +493,6 @@ module.exports = {
|
||||
class RenderedBBTextInstance extends RenderedInstance {
|
||||
constructor(
|
||||
project,
|
||||
layout,
|
||||
instance,
|
||||
associatedObjectConfiguration,
|
||||
pixiContainer,
|
||||
@@ -508,7 +500,6 @@ module.exports = {
|
||||
) {
|
||||
super(
|
||||
project,
|
||||
layout,
|
||||
instance,
|
||||
associatedObjectConfiguration,
|
||||
pixiContainer,
|
||||
|
@@ -134,17 +134,13 @@ module.exports = {
|
||||
objectContent,
|
||||
instance,
|
||||
propertyName,
|
||||
newValue,
|
||||
project,
|
||||
layout
|
||||
newValue
|
||||
) {
|
||||
return false;
|
||||
};
|
||||
bitmapTextObject.getInitialInstanceProperties = function (
|
||||
content,
|
||||
instance,
|
||||
project,
|
||||
layout
|
||||
instance
|
||||
) {
|
||||
var instanceProperties = new gd.MapStringPropertyDescriptor();
|
||||
return instanceProperties;
|
||||
@@ -641,7 +637,6 @@ module.exports = {
|
||||
|
||||
constructor(
|
||||
project,
|
||||
layout,
|
||||
instance,
|
||||
associatedObjectConfiguration,
|
||||
pixiContainer,
|
||||
@@ -649,7 +644,6 @@ module.exports = {
|
||||
) {
|
||||
super(
|
||||
project,
|
||||
layout,
|
||||
instance,
|
||||
associatedObjectConfiguration,
|
||||
pixiContainer,
|
||||
|
@@ -349,9 +349,7 @@ module.exports = {
|
||||
objectContent,
|
||||
instance,
|
||||
propertyName,
|
||||
newValue,
|
||||
project,
|
||||
layout
|
||||
newValue
|
||||
) {
|
||||
if (propertyName === 'My instance property') {
|
||||
instance.setRawStringProperty('instanceprop1', newValue);
|
||||
@@ -364,12 +362,7 @@ module.exports = {
|
||||
|
||||
return false;
|
||||
};
|
||||
dummyObject.getInitialInstanceProperties = function (
|
||||
content,
|
||||
instance,
|
||||
project,
|
||||
layout
|
||||
) {
|
||||
dummyObject.getInitialInstanceProperties = function (content, instance) {
|
||||
var instanceProperties = new gd.MapStringPropertyDescriptor();
|
||||
|
||||
instanceProperties
|
||||
@@ -475,7 +468,6 @@ module.exports = {
|
||||
class RenderedDummyObjectInstance extends RenderedInstance {
|
||||
constructor(
|
||||
project,
|
||||
layout,
|
||||
instance,
|
||||
associatedObjectConfiguration,
|
||||
pixiContainer,
|
||||
@@ -483,7 +475,6 @@ module.exports = {
|
||||
) {
|
||||
super(
|
||||
project,
|
||||
layout,
|
||||
instance,
|
||||
associatedObjectConfiguration,
|
||||
pixiContainer,
|
||||
|
@@ -381,6 +381,28 @@ module.exports = {
|
||||
.setFunctionName('gdjs.fileSystem.deleteFileAsync')
|
||||
.setAsyncFunctionName('gdjs.fileSystem.deleteFileAsyncTask');
|
||||
|
||||
extension
|
||||
.addAction(
|
||||
'ReadDirectory',
|
||||
_('Read a directory'),
|
||||
_(
|
||||
'Reads the contents of a directory (all files and sub-directories) and stores them in an array.'
|
||||
),
|
||||
_('Read the directory _PARAM0_ into _PARAM1_'),
|
||||
_('Windows, Linux, MacOS/Asynchronous'),
|
||||
'JsPlatform/Extensions/filesystem_delete_file32.png',
|
||||
'JsPlatform/Extensions/filesystem_delete_file32.png'
|
||||
)
|
||||
.addParameter('string', _('Directory path'), '', false)
|
||||
.addParameter('scenevar', _('Variable to store the result'), '', true)
|
||||
.setParameterLongDescription(
|
||||
'It is set to `"error"` if an error has occured, otherwise it is set to an array of all files and sub-directories present in the directory.'
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile('Extensions/FileSystem/filesystemtools.js')
|
||||
.setFunctionName('gdjs.fileSystem.readdir')
|
||||
.setAsyncFunctionName('gdjs.fileSystem.readdirAsync');
|
||||
|
||||
extension
|
||||
.addStrExpression(
|
||||
'DesktopPath',
|
||||
|
@@ -662,6 +662,56 @@ namespace gdjs {
|
||||
)
|
||||
: (resultVar.setString('error'), new gdjs.ResolveTask());
|
||||
|
||||
/**
|
||||
* Reads the contents of a directory.
|
||||
* @param directoryPath Path to the directory.
|
||||
* @param resultVar The variable where to store the result of the operation.
|
||||
*/
|
||||
export const readdir = function (
|
||||
directoryPath: string,
|
||||
resultVar: gdjs.Variable
|
||||
) {
|
||||
let result: string[] | string = 'error';
|
||||
if (fs) {
|
||||
try {
|
||||
result = fs.readdirSync(directoryPath);
|
||||
} catch (err) {
|
||||
logger.error(
|
||||
"Unable to read the directory: '" + directoryPath + "': ",
|
||||
err
|
||||
);
|
||||
result = 'error';
|
||||
}
|
||||
}
|
||||
resultVar.fromJSObject(result);
|
||||
};
|
||||
|
||||
/**
|
||||
* Read a directory's contents asynchronously.
|
||||
* @param directoryPath Path to the directory
|
||||
* @param resultVar The variable where to store the result of the operation
|
||||
*/
|
||||
export const readdirAsync = (
|
||||
directoryPath: string,
|
||||
resultVar: gdjs.Variable
|
||||
) =>
|
||||
asyncFs
|
||||
? new gdjs.PromiseTask(
|
||||
asyncFs
|
||||
.readdir(directoryPath)
|
||||
.then((results) => {
|
||||
resultVar.fromJSObject(results);
|
||||
})
|
||||
.catch((err) => {
|
||||
resultVar.setString('error');
|
||||
logger.error(
|
||||
"Unable to read the directory: '" + directoryPath + "': ",
|
||||
err
|
||||
);
|
||||
})
|
||||
)
|
||||
: (resultVar.setString('error'), new gdjs.ResolveTask());
|
||||
|
||||
/**
|
||||
* Check if the file or directory exists.
|
||||
* @param filePath The path to the file or directory
|
||||
|
4
Extensions/JsExtensionTypes.d.ts
vendored
4
Extensions/JsExtensionTypes.d.ts
vendored
@@ -10,7 +10,6 @@ declare namespace PIXI {}
|
||||
*/
|
||||
class RenderedInstance {
|
||||
_project: gd.Project;
|
||||
_layout: gd.Layout;
|
||||
_instance: gd.InitialInstance;
|
||||
_associatedObjectConfiguration: gd.ObjectConfiguration;
|
||||
_pixiContainer: PIXI.Container;
|
||||
@@ -20,7 +19,6 @@ class RenderedInstance {
|
||||
|
||||
constructor(
|
||||
project: gdProject,
|
||||
layout: gdLayout,
|
||||
instance: gdInitialInstance,
|
||||
associatedObjectConfiguration: gdObjectConfiguration,
|
||||
pixiContainer: PIXI.Container,
|
||||
@@ -86,7 +84,6 @@ class RenderedInstance {
|
||||
*/
|
||||
class Rendered3DInstance {
|
||||
_project: gdProject;
|
||||
_layout: gdLayout;
|
||||
_instance: gdInitialInstance;
|
||||
_associatedObjectConfiguration: gdObjectConfiguration;
|
||||
_pixiContainer: PIXI.Container;
|
||||
@@ -98,7 +95,6 @@ class Rendered3DInstance {
|
||||
|
||||
constructor(
|
||||
project: gdProject,
|
||||
layout: gdLayout,
|
||||
instance: gdInitialInstance,
|
||||
associatedObjectConfiguration: gdObjectConfiguration,
|
||||
pixiContainer: PIXI.Container,
|
||||
|
@@ -153,19 +153,12 @@ module.exports = {
|
||||
objectContent,
|
||||
instance,
|
||||
propertyName,
|
||||
newValue,
|
||||
project,
|
||||
layout
|
||||
newValue
|
||||
) {
|
||||
return false;
|
||||
};
|
||||
|
||||
lightObject.getInitialInstanceProperties = function (
|
||||
content,
|
||||
instance,
|
||||
project,
|
||||
layout
|
||||
) {
|
||||
lightObject.getInitialInstanceProperties = function (content, instance) {
|
||||
const instanceProperties = new gd.MapStringPropertyDescriptor();
|
||||
|
||||
return instanceProperties;
|
||||
@@ -247,7 +240,6 @@ module.exports = {
|
||||
class RenderedLightObjectInstance extends RenderedInstance {
|
||||
constructor(
|
||||
project,
|
||||
layout,
|
||||
instance,
|
||||
associatedObjectConfiguration,
|
||||
pixiContainer,
|
||||
@@ -255,7 +247,6 @@ module.exports = {
|
||||
) {
|
||||
super(
|
||||
project,
|
||||
layout,
|
||||
instance,
|
||||
associatedObjectConfiguration,
|
||||
pixiContainer,
|
||||
|
@@ -46,8 +46,8 @@ module.exports = {
|
||||
.addCodeOnlyParameter('currentScene', '')
|
||||
.setHelpPath('/all-features/multiplayer')
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile('Extensions/P2P/A_peer.js')
|
||||
.addIncludeFile('Extensions/P2P/B_p2ptools.js')
|
||||
.setIncludeFile('Extensions/Multiplayer/peer.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/peerJsHelper.js')
|
||||
.addIncludeFile(
|
||||
'Extensions/PlayerAuthentication/playerauthenticationcomponents.js'
|
||||
)
|
||||
@@ -74,8 +74,8 @@ module.exports = {
|
||||
.addParameter('yesorno', _('Show close button'), '', false)
|
||||
.setHelpPath('/all-features/multiplayer')
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile('Extensions/P2P/A_peer.js')
|
||||
.addIncludeFile('Extensions/P2P/B_p2ptools.js')
|
||||
.setIncludeFile('Extensions/Multiplayer/peer.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/peerJsHelper.js')
|
||||
.addIncludeFile(
|
||||
'Extensions/PlayerAuthentication/playerauthenticationcomponents.js'
|
||||
)
|
||||
@@ -102,8 +102,8 @@ module.exports = {
|
||||
)
|
||||
.setHelpPath('/all-features/multiplayer')
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile('Extensions/P2P/A_peer.js')
|
||||
.addIncludeFile('Extensions/P2P/B_p2ptools.js')
|
||||
.setIncludeFile('Extensions/Multiplayer/peer.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/peerJsHelper.js')
|
||||
.addIncludeFile(
|
||||
'Extensions/PlayerAuthentication/playerauthenticationcomponents.js'
|
||||
)
|
||||
@@ -116,6 +116,34 @@ module.exports = {
|
||||
.addIncludeFile('Extensions/Multiplayer/multiplayertools.js')
|
||||
.setFunctionName('gdjs.multiplayer.endLobbyGame');
|
||||
|
||||
extension
|
||||
.addAction(
|
||||
'LeaveGameLobby',
|
||||
_('Leave Game Lobby'),
|
||||
_(
|
||||
'Leave the current game lobby. This will trigger the "Player has left" condition on the other players, and the "Lobby game has ended" condition on the player leaving.'
|
||||
),
|
||||
_('Leave the game lobby'),
|
||||
_('Lobbies'),
|
||||
'JsPlatform/Extensions/multiplayer.svg',
|
||||
'JsPlatform/Extensions/multiplayer.svg'
|
||||
)
|
||||
.setHelpPath('/all-features/multiplayer')
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile('Extensions/Multiplayer/peer.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/peerJsHelper.js')
|
||||
.addIncludeFile(
|
||||
'Extensions/PlayerAuthentication/playerauthenticationcomponents.js'
|
||||
)
|
||||
.addIncludeFile(
|
||||
'Extensions/PlayerAuthentication/playerauthenticationtools.js'
|
||||
)
|
||||
.addIncludeFile('Extensions/Multiplayer/multiplayercomponents.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/messageManager.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/multiplayerVariablesManager.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/multiplayertools.js')
|
||||
.setFunctionName('gdjs.multiplayer.leaveGameLobby');
|
||||
|
||||
extension
|
||||
.addAction(
|
||||
'SendMessage',
|
||||
@@ -132,8 +160,8 @@ module.exports = {
|
||||
.addParameter('string', _('Message name'), '', false)
|
||||
.addParameter('string', _('Message content'), '', false)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile('Extensions/P2P/A_peer.js')
|
||||
.addIncludeFile('Extensions/P2P/B_p2ptools.js')
|
||||
.setIncludeFile('Extensions/Multiplayer/peer.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/peerJsHelper.js')
|
||||
.addIncludeFile(
|
||||
'Extensions/PlayerAuthentication/playerauthenticationcomponents.js'
|
||||
)
|
||||
@@ -144,7 +172,71 @@ module.exports = {
|
||||
.addIncludeFile('Extensions/Multiplayer/messageManager.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/multiplayerVariablesManager.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/multiplayertools.js')
|
||||
.setFunctionName('gdjs.multiplayerMessageManager.sendMessage');
|
||||
.setFunctionName('gdjs.multiplayerMessageManager.sendCustomMessage');
|
||||
|
||||
extension
|
||||
.addAction(
|
||||
'SendVariableMessage',
|
||||
_('Send custom message to other players with a variable'),
|
||||
_(
|
||||
"Send a custom message to other players in the lobby containing a variable, with an automatic retry system if it hasn't been received. Use with the condition 'Message has been received' to know when the message has been properly processed by the host."
|
||||
),
|
||||
_('Send message _PARAM0_ to other players with variable _PARAM1_'),
|
||||
_('Advanced'),
|
||||
'JsPlatform/Extensions/multiplayer.svg',
|
||||
'JsPlatform/Extensions/multiplayer.svg'
|
||||
)
|
||||
.setHelpPath('/all-features/multiplayer')
|
||||
.addParameter('string', _('Message name'), '', false)
|
||||
.addParameter('variable', _('Variable'), '', false)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile('Extensions/Multiplayer/peer.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/peerJsHelper.js')
|
||||
.addIncludeFile(
|
||||
'Extensions/PlayerAuthentication/playerauthenticationcomponents.js'
|
||||
)
|
||||
.addIncludeFile(
|
||||
'Extensions/PlayerAuthentication/playerauthenticationtools.js'
|
||||
)
|
||||
.addIncludeFile('Extensions/Multiplayer/multiplayercomponents.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/messageManager.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/multiplayerVariablesManager.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/multiplayertools.js')
|
||||
.setFunctionName(
|
||||
'gdjs.multiplayerMessageManager.sendVariableCustomMessage'
|
||||
);
|
||||
|
||||
extension
|
||||
.addAction(
|
||||
'GetMessageVariable',
|
||||
_('Get message variable'),
|
||||
_(
|
||||
"Store the data of the specified message in a variable. Use with the condition 'Message has been received' to know when the message has been properly processed by the host."
|
||||
),
|
||||
_('Save message _PARAM0_ data in _PARAM1_'),
|
||||
_('Advanced'),
|
||||
'JsPlatform/Extensions/multiplayer.svg',
|
||||
'JsPlatform/Extensions/multiplayer.svg'
|
||||
)
|
||||
.setHelpPath('/all-features/multiplayer')
|
||||
.addParameter('string', _('Message name'), '', false)
|
||||
.addParameter('variable', _('Variable'), '', false)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile('Extensions/Multiplayer/peer.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/peerJsHelper.js')
|
||||
.addIncludeFile(
|
||||
'Extensions/PlayerAuthentication/playerauthenticationcomponents.js'
|
||||
)
|
||||
.addIncludeFile(
|
||||
'Extensions/PlayerAuthentication/playerauthenticationtools.js'
|
||||
)
|
||||
.addIncludeFile('Extensions/Multiplayer/multiplayercomponents.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/messageManager.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/multiplayerVariablesManager.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/multiplayertools.js')
|
||||
.setFunctionName(
|
||||
'gdjs.multiplayerMessageManager.getVariableCustomMessageData'
|
||||
);
|
||||
|
||||
extension
|
||||
.addCondition(
|
||||
@@ -158,8 +250,8 @@ module.exports = {
|
||||
)
|
||||
.addCodeOnlyParameter('currentScene', '')
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile('Extensions/P2P/A_peer.js')
|
||||
.addIncludeFile('Extensions/P2P/B_p2ptools.js')
|
||||
.setIncludeFile('Extensions/Multiplayer/peer.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/peerJsHelper.js')
|
||||
.addIncludeFile(
|
||||
'Extensions/PlayerAuthentication/playerauthenticationcomponents.js'
|
||||
)
|
||||
@@ -183,8 +275,8 @@ module.exports = {
|
||||
'JsPlatform/Extensions/multiplayer.svg'
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile('Extensions/P2P/A_peer.js')
|
||||
.addIncludeFile('Extensions/P2P/B_p2ptools.js')
|
||||
.setIncludeFile('Extensions/Multiplayer/peer.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/peerJsHelper.js')
|
||||
.addIncludeFile(
|
||||
'Extensions/PlayerAuthentication/playerauthenticationcomponents.js'
|
||||
)
|
||||
@@ -208,8 +300,8 @@ module.exports = {
|
||||
'JsPlatform/Extensions/multiplayer.svg'
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile('Extensions/P2P/A_peer.js')
|
||||
.addIncludeFile('Extensions/P2P/B_p2ptools.js')
|
||||
.setIncludeFile('Extensions/Multiplayer/peer.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/peerJsHelper.js')
|
||||
.addIncludeFile(
|
||||
'Extensions/PlayerAuthentication/playerauthenticationcomponents.js'
|
||||
)
|
||||
@@ -233,8 +325,8 @@ module.exports = {
|
||||
'JsPlatform/Extensions/multiplayer.svg'
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile('Extensions/P2P/A_peer.js')
|
||||
.addIncludeFile('Extensions/P2P/B_p2ptools.js')
|
||||
.setIncludeFile('Extensions/Multiplayer/peer.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/peerJsHelper.js')
|
||||
.addIncludeFile(
|
||||
'Extensions/PlayerAuthentication/playerauthenticationcomponents.js'
|
||||
)
|
||||
@@ -261,8 +353,8 @@ module.exports = {
|
||||
)
|
||||
.addParameter('string', _('Message name'), '', false)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile('Extensions/P2P/A_peer.js')
|
||||
.addIncludeFile('Extensions/P2P/B_p2ptools.js')
|
||||
.setIncludeFile('Extensions/Multiplayer/peer.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/peerJsHelper.js')
|
||||
.addIncludeFile(
|
||||
'Extensions/PlayerAuthentication/playerauthenticationcomponents.js'
|
||||
)
|
||||
@@ -273,7 +365,9 @@ module.exports = {
|
||||
.addIncludeFile('Extensions/Multiplayer/messageManager.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/multiplayerVariablesManager.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/multiplayertools.js')
|
||||
.setFunctionName('gdjs.multiplayerMessageManager.hasMessageBeenReceived');
|
||||
.setFunctionName(
|
||||
'gdjs.multiplayerMessageManager.hasCustomMessageBeenReceived'
|
||||
);
|
||||
|
||||
extension
|
||||
.addCondition(
|
||||
@@ -286,8 +380,8 @@ module.exports = {
|
||||
'JsPlatform/Extensions/multiplayer.svg'
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile('Extensions/P2P/A_peer.js')
|
||||
.addIncludeFile('Extensions/P2P/B_p2ptools.js')
|
||||
.setIncludeFile('Extensions/Multiplayer/peer.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/peerJsHelper.js')
|
||||
.addIncludeFile(
|
||||
'Extensions/PlayerAuthentication/playerauthenticationcomponents.js'
|
||||
)
|
||||
@@ -311,8 +405,8 @@ module.exports = {
|
||||
'JsPlatform/Extensions/multiplayer.svg'
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile('Extensions/P2P/A_peer.js')
|
||||
.addIncludeFile('Extensions/P2P/B_p2ptools.js')
|
||||
.setIncludeFile('Extensions/Multiplayer/peer.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/peerJsHelper.js')
|
||||
.addIncludeFile(
|
||||
'Extensions/PlayerAuthentication/playerauthenticationcomponents.js'
|
||||
)
|
||||
@@ -337,8 +431,8 @@ module.exports = {
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.addParameter('number', _('Player number'), '', false)
|
||||
.setIncludeFile('Extensions/P2P/A_peer.js')
|
||||
.addIncludeFile('Extensions/P2P/B_p2ptools.js')
|
||||
.setIncludeFile('Extensions/Multiplayer/peer.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/peerJsHelper.js')
|
||||
.addIncludeFile(
|
||||
'Extensions/PlayerAuthentication/playerauthenticationcomponents.js'
|
||||
)
|
||||
@@ -363,8 +457,8 @@ module.exports = {
|
||||
)
|
||||
.addParameter('string', _('Message name'), '', false)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile('Extensions/P2P/A_peer.js')
|
||||
.addIncludeFile('Extensions/P2P/B_p2ptools.js')
|
||||
.setIncludeFile('Extensions/Multiplayer/peer.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/peerJsHelper.js')
|
||||
.addIncludeFile(
|
||||
'Extensions/PlayerAuthentication/playerauthenticationcomponents.js'
|
||||
)
|
||||
@@ -375,7 +469,31 @@ module.exports = {
|
||||
.addIncludeFile('Extensions/Multiplayer/messageManager.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/multiplayerVariablesManager.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/multiplayertools.js')
|
||||
.setFunctionName('gdjs.multiplayerMessageManager.getMessageData');
|
||||
.setFunctionName('gdjs.multiplayerMessageManager.getCustomMessageData');
|
||||
|
||||
extension
|
||||
.addExpression(
|
||||
'MessageSender',
|
||||
_('Message sender'),
|
||||
_('Returns the player number of the sender of the specified message.'),
|
||||
_('Advanced'),
|
||||
'JsPlatform/Extensions/multiplayer.svg'
|
||||
)
|
||||
.addParameter('string', _('Message name'), '', false)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile('Extensions/Multiplayer/peer.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/peerJsHelper.js')
|
||||
.addIncludeFile(
|
||||
'Extensions/PlayerAuthentication/playerauthenticationcomponents.js'
|
||||
)
|
||||
.addIncludeFile(
|
||||
'Extensions/PlayerAuthentication/playerauthenticationtools.js'
|
||||
)
|
||||
.addIncludeFile('Extensions/Multiplayer/multiplayercomponents.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/messageManager.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/multiplayerVariablesManager.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/multiplayertools.js')
|
||||
.setFunctionName('gdjs.multiplayerMessageManager.getCustomMessageSender');
|
||||
|
||||
extension
|
||||
.addExpressionAndCondition(
|
||||
@@ -387,8 +505,8 @@ module.exports = {
|
||||
_('Lobbies'),
|
||||
'JsPlatform/Extensions/multiplayer.svg'
|
||||
)
|
||||
.setIncludeFile('Extensions/P2P/A_peer.js')
|
||||
.addIncludeFile('Extensions/P2P/B_p2ptools.js')
|
||||
.setIncludeFile('Extensions/Multiplayer/peer.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/peerJsHelper.js')
|
||||
.addIncludeFile(
|
||||
'Extensions/PlayerAuthentication/playerauthenticationcomponents.js'
|
||||
)
|
||||
@@ -412,8 +530,8 @@ module.exports = {
|
||||
_('Lobbies'),
|
||||
'JsPlatform/Extensions/multiplayer.svg'
|
||||
)
|
||||
.setIncludeFile('Extensions/P2P/A_peer.js')
|
||||
.addIncludeFile('Extensions/P2P/B_p2ptools.js')
|
||||
.setIncludeFile('Extensions/Multiplayer/peer.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/peerJsHelper.js')
|
||||
.addIncludeFile(
|
||||
'Extensions/PlayerAuthentication/playerauthenticationcomponents.js'
|
||||
)
|
||||
@@ -442,8 +560,8 @@ module.exports = {
|
||||
false
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile('Extensions/P2P/A_peer.js')
|
||||
.addIncludeFile('Extensions/P2P/B_p2ptools.js')
|
||||
.setIncludeFile('Extensions/Multiplayer/peer.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/peerJsHelper.js')
|
||||
.addIncludeFile(
|
||||
'Extensions/PlayerAuthentication/playerauthenticationcomponents.js'
|
||||
)
|
||||
@@ -465,8 +583,8 @@ module.exports = {
|
||||
'JsPlatform/Extensions/multiplayer.svg'
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile('Extensions/P2P/A_peer.js')
|
||||
.addIncludeFile('Extensions/P2P/B_p2ptools.js')
|
||||
.setIncludeFile('Extensions/Multiplayer/peer.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/peerJsHelper.js')
|
||||
.addIncludeFile(
|
||||
'Extensions/PlayerAuthentication/playerauthenticationcomponents.js'
|
||||
)
|
||||
@@ -494,8 +612,8 @@ module.exports = {
|
||||
false
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile('Extensions/P2P/A_peer.js')
|
||||
.addIncludeFile('Extensions/P2P/B_p2ptools.js')
|
||||
.setIncludeFile('Extensions/Multiplayer/peer.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/peerJsHelper.js')
|
||||
.addIncludeFile(
|
||||
'Extensions/PlayerAuthentication/playerauthenticationcomponents.js'
|
||||
)
|
||||
@@ -517,8 +635,8 @@ module.exports = {
|
||||
'JsPlatform/Extensions/multiplayer.svg'
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile('Extensions/P2P/A_peer.js')
|
||||
.addIncludeFile('Extensions/P2P/B_p2ptools.js')
|
||||
.setIncludeFile('Extensions/Multiplayer/peer.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/peerJsHelper.js')
|
||||
.addIncludeFile(
|
||||
'Extensions/PlayerAuthentication/playerauthenticationcomponents.js'
|
||||
)
|
||||
@@ -547,8 +665,8 @@ module.exports = {
|
||||
'number',
|
||||
gd.ParameterOptions.makeNewOptions().setDescription(_('Player number'))
|
||||
)
|
||||
.setIncludeFile('Extensions/P2P/A_peer.js')
|
||||
.addIncludeFile('Extensions/P2P/B_p2ptools.js')
|
||||
.setIncludeFile('Extensions/Multiplayer/peer.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/peerJsHelper.js')
|
||||
.addIncludeFile(
|
||||
'Extensions/PlayerAuthentication/playerauthenticationcomponents.js'
|
||||
)
|
||||
@@ -579,8 +697,8 @@ module.exports = {
|
||||
.addParameter('variable', _('Variable'), '', false)
|
||||
.setHelpPath('/all-features/multiplayer')
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile('Extensions/P2P/A_peer.js')
|
||||
.addIncludeFile('Extensions/P2P/B_p2ptools.js')
|
||||
.setIncludeFile('Extensions/Multiplayer/peer.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/peerJsHelper.js')
|
||||
.addIncludeFile(
|
||||
'Extensions/PlayerAuthentication/playerauthenticationcomponents.js'
|
||||
)
|
||||
@@ -610,8 +728,8 @@ module.exports = {
|
||||
.addParameter('variable', _('Variable'), '', false)
|
||||
.setHelpPath('/all-features/multiplayer')
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile('Extensions/P2P/A_peer.js')
|
||||
.addIncludeFile('Extensions/P2P/B_p2ptools.js')
|
||||
.setIncludeFile('Extensions/Multiplayer/peer.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/peerJsHelper.js')
|
||||
.addIncludeFile(
|
||||
'Extensions/PlayerAuthentication/playerauthenticationcomponents.js'
|
||||
)
|
||||
@@ -641,8 +759,8 @@ module.exports = {
|
||||
.addParameter('variable', _('Variable'), '', false)
|
||||
.setHelpPath('/all-features/multiplayer')
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile('Extensions/P2P/A_peer.js')
|
||||
.addIncludeFile('Extensions/P2P/B_p2ptools.js')
|
||||
.setIncludeFile('Extensions/Multiplayer/peer.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/peerJsHelper.js')
|
||||
.addIncludeFile(
|
||||
'Extensions/PlayerAuthentication/playerauthenticationcomponents.js'
|
||||
)
|
||||
@@ -747,8 +865,8 @@ module.exports = {
|
||||
multiplayerObjectBehavior,
|
||||
sharedData
|
||||
)
|
||||
.setIncludeFile('Extensions/P2P/A_peer.js')
|
||||
.addIncludeFile('Extensions/P2P/B_p2ptools.js')
|
||||
.setIncludeFile('Extensions/Multiplayer/peer.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/peerJsHelper.js')
|
||||
.addIncludeFile(
|
||||
'Extensions/PlayerAuthentication/playerauthenticationcomponents.js'
|
||||
)
|
||||
@@ -769,7 +887,7 @@ module.exports = {
|
||||
_('Player object ownership'),
|
||||
_('the player owning the object'),
|
||||
_('the player owning the instance'),
|
||||
_('Objects'),
|
||||
_('Multiplayer'),
|
||||
'JsPlatform/Extensions/multiplayer.svg'
|
||||
)
|
||||
.addParameter('object', _('Object'), '', false)
|
||||
@@ -790,7 +908,7 @@ module.exports = {
|
||||
'Check if the object is owned by the current player, as a player or the host.'
|
||||
),
|
||||
_('Object _PARAM0_ is owned by current player'),
|
||||
_('Objects'),
|
||||
_('Multiplayer'),
|
||||
'JsPlatform/Extensions/multiplayer.svg',
|
||||
'JsPlatform/Extensions/multiplayer.svg'
|
||||
)
|
||||
@@ -812,7 +930,7 @@ module.exports = {
|
||||
'Take the ownership of the object. It will then be synchronized to other players, with the current player as the owner.'
|
||||
),
|
||||
_('Take ownership of _PARAM0_'),
|
||||
_('Objects'),
|
||||
_('Multiplayer'),
|
||||
'JsPlatform/Extensions/multiplayer.svg',
|
||||
'JsPlatform/Extensions/multiplayer.svg'
|
||||
)
|
||||
@@ -834,7 +952,7 @@ module.exports = {
|
||||
'Remove the ownership of the object from the player. It will still be synchronized to other players, but the host owns it.'
|
||||
),
|
||||
_('Remove ownership of _PARAM0_'),
|
||||
_('Objects'),
|
||||
_('Multiplayer'),
|
||||
'JsPlatform/Extensions/multiplayer.svg',
|
||||
'JsPlatform/Extensions/multiplayer.svg'
|
||||
)
|
||||
@@ -848,6 +966,30 @@ module.exports = {
|
||||
.markAsAdvanced()
|
||||
.setFunctionName('removeObjectOwnership');
|
||||
|
||||
behavior
|
||||
.addScopedAction(
|
||||
'EnableBehaviorSynchronization',
|
||||
_('Enable (or disable) the synchronization of a behavior'),
|
||||
_(
|
||||
"Enable or disable the synchronization of a behavior over the network. If disabled, the behavior's current state will not be sent to other players anymore."
|
||||
),
|
||||
_('Enable synchronization of _PARAM2_ for _PARAM0_: _PARAM3_'),
|
||||
_('Multiplayer'),
|
||||
'JsPlatform/Extensions/multiplayer.svg',
|
||||
'JsPlatform/Extensions/multiplayer.svg'
|
||||
)
|
||||
.addParameter('object', _('Object'), '', false)
|
||||
.addParameter(
|
||||
'behavior',
|
||||
_('Multiplayer behavior'),
|
||||
'MultiplayerObjectBehavior',
|
||||
false
|
||||
)
|
||||
.addParameter('behavior', _('Object behavior'), '', false)
|
||||
.addParameter('yesorno', _('Enable synchronization'), '', false)
|
||||
.markAsAdvanced()
|
||||
.setFunctionName('enableBehaviorSynchronization');
|
||||
|
||||
return extension;
|
||||
},
|
||||
runExtensionSanityTests: function (gd, extension) {
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -228,7 +228,7 @@ namespace gdjs {
|
||||
// Before sending the change owner message, if we are becoming the new owner,
|
||||
// we want to ensure this message is acknowledged, by everyone we're connected to.
|
||||
if (variableData.newVariableOwner === currentPlayerNumber) {
|
||||
const otherPeerIds = gdjs.evtTools.p2p.getAllPeers();
|
||||
const otherPeerIds = gdjs.multiplayerPeerJsHelper.getAllPeers();
|
||||
const variableOwnerChangedMessageName = gdjs.multiplayerMessageManager.createVariableOwnerChangedMessageNameFromChangeVariableOwnerMessage(
|
||||
messageName
|
||||
);
|
||||
@@ -243,14 +243,12 @@ namespace gdjs {
|
||||
}
|
||||
|
||||
debugLogger.info('Sending change owner message', messageName);
|
||||
const connectedPeerIds = gdjs.evtTools.p2p.getAllPeers();
|
||||
for (const peerId of connectedPeerIds) {
|
||||
gdjs.multiplayerMessageManager.sendDataTo(
|
||||
peerId,
|
||||
messageName,
|
||||
messageData
|
||||
);
|
||||
}
|
||||
const connectedPeerIds = gdjs.multiplayerPeerJsHelper.getAllPeers();
|
||||
gdjs.multiplayerMessageManager.sendDataTo(
|
||||
connectedPeerIds,
|
||||
messageName,
|
||||
messageData
|
||||
);
|
||||
|
||||
// Remove the variable from the list of variables ownership changes to sync.
|
||||
delete variableOwnershipChangesToSyncAtEndOfFrame[variableNetworkId];
|
||||
|
@@ -101,17 +101,19 @@ namespace gdjs {
|
||||
}, this._timeBeforeDestroyingObjectWithoutNetworkIdInMs);
|
||||
}
|
||||
|
||||
private _sendDataToPeersWithIncreasedClock(
|
||||
private _sendDataToPeersWithIncreasedClock = async (
|
||||
messageName: string,
|
||||
data: Object
|
||||
) {
|
||||
) => {
|
||||
this._clock++;
|
||||
data['_clock'] = this._clock;
|
||||
const connectedPeerIds = gdjs.evtTools.p2p.getAllPeers();
|
||||
for (const peerId of connectedPeerIds) {
|
||||
gdjs.multiplayerMessageManager.sendDataTo(peerId, messageName, data);
|
||||
}
|
||||
}
|
||||
const connectedPeerIds = gdjs.multiplayerPeerJsHelper.getAllPeers();
|
||||
await gdjs.multiplayerMessageManager.sendDataTo(
|
||||
connectedPeerIds,
|
||||
messageName,
|
||||
data
|
||||
);
|
||||
};
|
||||
|
||||
private _isOwnerAsPlayerOrHost() {
|
||||
const currentPlayerNumber = gdjs.multiplayer.getCurrentPlayerNumber();
|
||||
@@ -453,7 +455,7 @@ namespace gdjs {
|
||||
// If we are player 1, we are connected to everyone, so we expect an acknowledgment from everyone.
|
||||
// If we are another player, we are only connected to player 1, so we expect an acknowledgment from player 1.
|
||||
// In both cases, this represents the list of peers the current user is connected to.
|
||||
const otherPeerIds = gdjs.evtTools.p2p.getAllPeers();
|
||||
const otherPeerIds = gdjs.multiplayerPeerJsHelper.getAllPeers();
|
||||
const {
|
||||
messageName: destroyMessageName,
|
||||
messageData: destroyMessageData,
|
||||
@@ -563,7 +565,7 @@ namespace gdjs {
|
||||
// If we are another player, we are only connected to player 1, so we expect an acknowledgment from player 1.
|
||||
// In both cases, this represents the list of peers the current user is connected to.
|
||||
if (newObjectPlayerNumber === currentPlayerNumber) {
|
||||
const otherPeerIds = gdjs.evtTools.p2p.getAllPeers();
|
||||
const otherPeerIds = gdjs.multiplayerPeerJsHelper.getAllPeers();
|
||||
const changeOwnerAcknowledgedMessageName = gdjs.multiplayerMessageManager.createInstanceOwnerChangedMessageNameFromChangeInstanceOwnerMessage(
|
||||
messageName
|
||||
);
|
||||
@@ -586,6 +588,9 @@ namespace gdjs {
|
||||
// If we are the new owner, also send directly an update of the position,
|
||||
// so that the object is immediately moved on the screen and we don't wait for the next tick.
|
||||
if (newObjectPlayerNumber === currentPlayerNumber) {
|
||||
debugLogger.info(
|
||||
'Sending update message to move the object immediately.'
|
||||
);
|
||||
const objectNetworkSyncData = this.owner.getNetworkSyncData();
|
||||
const {
|
||||
messageName: updateMessageName,
|
||||
@@ -624,6 +629,18 @@ namespace gdjs {
|
||||
getActionOnPlayerDisconnect() {
|
||||
return this.actionOnPlayerDisconnect;
|
||||
}
|
||||
|
||||
enableBehaviorSynchronization(behaviorName: string, enable: boolean) {
|
||||
const behavior = this.owner.getBehavior(behaviorName);
|
||||
if (!behavior) {
|
||||
logger.error(
|
||||
`Behavior ${behaviorName} does not exist on object ${this.owner.getName()}.`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
behavior.enableSynchronization(enable);
|
||||
}
|
||||
}
|
||||
gdjs.registerBehavior(
|
||||
'Multiplayer::MultiplayerObjectBehavior',
|
||||
|
@@ -1,24 +1,26 @@
|
||||
namespace gdjs {
|
||||
const logger = new gdjs.Logger('Multiplayer');
|
||||
|
||||
type Lobby = {
|
||||
id: string;
|
||||
name: string;
|
||||
status: string;
|
||||
players: { playerId: string; status: string }[];
|
||||
};
|
||||
export namespace multiplayer {
|
||||
/** Set to true in testing to avoid relying on the multiplayer extension. */
|
||||
export let disableMultiplayerForTesting = false;
|
||||
|
||||
let _isGameRegistered: boolean | null = null;
|
||||
let _isCheckingIfGameIsRegistered = false;
|
||||
let _isWaitingForLoginCallback = false;
|
||||
let _isWaitingForLogin = false;
|
||||
|
||||
let _hasLobbyGameJustStarted = false;
|
||||
export let _isLobbyGameRunning = false;
|
||||
let _hasLobbyGameJustEnded = false;
|
||||
let _lobbyId: string | null = null;
|
||||
let _connectionId: string | null = null;
|
||||
export let _lobby: {
|
||||
id: string;
|
||||
name: string;
|
||||
status: string;
|
||||
players: { playerId: string; status: string }[];
|
||||
} | null = null;
|
||||
export let _lobby: Lobby | null = null;
|
||||
let _playerPublicProfiles: { id: string; username?: string }[] = [];
|
||||
|
||||
// Communication methods.
|
||||
@@ -29,6 +31,7 @@ namespace gdjs {
|
||||
|
||||
const DEFAULT_WEBSOCKET_HEARTBEAT_INTERVAL = 10000;
|
||||
const DEFAULT_LOBBY_HEARTBEAT_INTERVAL = 30000;
|
||||
const DEFAULT_COUNTDOWN_SECONDS_TO_START = 5;
|
||||
|
||||
// Save if we are on dev environment so we don't need to use the runtimeGame every time.
|
||||
let isUsingGDevelopDevelopmentEnvironment = false;
|
||||
@@ -407,15 +410,17 @@ namespace gdjs {
|
||||
// When socket is open, ask for the connectionId and send more session info, so that we can inform the lobbies window.
|
||||
if (_websocket) {
|
||||
_websocket.send(JSON.stringify({ action: 'getConnectionId' }));
|
||||
const plarformInfo = runtimeScene.getGame().getPlatformInfo();
|
||||
const platformInfo = runtimeScene.getGame().getPlatformInfo();
|
||||
_websocket.send(
|
||||
JSON.stringify({
|
||||
action: 'sessionInformation',
|
||||
connectionType: 'lobby',
|
||||
isCordova: plarformInfo.isCordova,
|
||||
devicePlatform: plarformInfo.devicePlatform,
|
||||
navigatorPlatform: plarformInfo.navigatorPlatform,
|
||||
hasTouch: plarformInfo.hasTouch,
|
||||
isCordova: platformInfo.isCordova,
|
||||
devicePlatform: platformInfo.devicePlatform,
|
||||
navigatorPlatform: platformInfo.navigatorPlatform,
|
||||
hasTouch: platformInfo.hasTouch,
|
||||
supportedCompressionMethods:
|
||||
platformInfo.supportedCompressionMethods,
|
||||
})
|
||||
);
|
||||
}
|
||||
@@ -461,11 +466,24 @@ namespace gdjs {
|
||||
logger.error('No lobby received');
|
||||
return;
|
||||
}
|
||||
handleLobbyUpdatedEvent(runtimeScene, lobby, positionInLobby);
|
||||
handleLobbyUpdatedEvent({
|
||||
runtimeScene,
|
||||
updatedLobby: lobby,
|
||||
positionInLobby,
|
||||
});
|
||||
break;
|
||||
}
|
||||
case 'gameCountdownStarted': {
|
||||
handleGameCountdownStartedEvent(runtimeScene);
|
||||
const messageData = messageContent.data;
|
||||
const compressionMethod = messageData.compressionMethod || 'none';
|
||||
const secondsToStart =
|
||||
messageData.secondsToStart ||
|
||||
DEFAULT_COUNTDOWN_SECONDS_TO_START;
|
||||
handleGameCountdownStartedEvent({
|
||||
runtimeScene,
|
||||
compressionMethod,
|
||||
secondsToStart,
|
||||
});
|
||||
break;
|
||||
}
|
||||
case 'gameStarted': {
|
||||
@@ -474,7 +492,7 @@ namespace gdjs {
|
||||
messageData.heartbeatInterval ||
|
||||
DEFAULT_LOBBY_HEARTBEAT_INTERVAL;
|
||||
|
||||
handleGameStartedEvent(runtimeScene, heartbeatInterval);
|
||||
handleGameStartedEvent({ runtimeScene, heartbeatInterval });
|
||||
break;
|
||||
}
|
||||
case 'peerId': {
|
||||
@@ -489,7 +507,7 @@ namespace gdjs {
|
||||
return;
|
||||
}
|
||||
|
||||
handlePeerIdEvent(peerId);
|
||||
handlePeerIdEvent({ peerId });
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -562,7 +580,7 @@ namespace gdjs {
|
||||
// When the connectionId is received, initialise PeerJS so players can connect to each others afterwards.
|
||||
if (validIceServers.length) {
|
||||
for (const server of validIceServers) {
|
||||
gdjs.evtTools.p2p.useCustomICECandidate(
|
||||
gdjs.multiplayerPeerJsHelper.useCustomICECandidate(
|
||||
server.urls,
|
||||
server.username,
|
||||
server.credential
|
||||
@@ -570,7 +588,7 @@ namespace gdjs {
|
||||
}
|
||||
}
|
||||
if (brokerServerConfig) {
|
||||
gdjs.evtTools.p2p.useCustomBrokerServer(
|
||||
gdjs.multiplayerPeerJsHelper.useCustomBrokerServer(
|
||||
brokerServerConfig.hostname,
|
||||
brokerServerConfig.port,
|
||||
brokerServerConfig.path,
|
||||
@@ -578,7 +596,7 @@ namespace gdjs {
|
||||
brokerServerConfig.secure
|
||||
);
|
||||
} else {
|
||||
gdjs.evtTools.p2p.useDefaultBrokerServer();
|
||||
gdjs.multiplayerPeerJsHelper.useDefaultBrokerServer();
|
||||
}
|
||||
|
||||
_connectionId = connectionId;
|
||||
@@ -625,11 +643,15 @@ namespace gdjs {
|
||||
_websocket = null;
|
||||
};
|
||||
|
||||
const handleLobbyUpdatedEvent = function (
|
||||
runtimeScene: gdjs.RuntimeScene,
|
||||
const handleLobbyUpdatedEvent = function ({
|
||||
runtimeScene,
|
||||
updatedLobby,
|
||||
positionInLobby: number
|
||||
) {
|
||||
positionInLobby,
|
||||
}: {
|
||||
runtimeScene: gdjs.RuntimeScene;
|
||||
updatedLobby: Lobby;
|
||||
positionInLobby: number;
|
||||
}) {
|
||||
// Update the object representing the lobby in the extension.
|
||||
_lobby = updatedLobby;
|
||||
|
||||
@@ -663,9 +685,17 @@ namespace gdjs {
|
||||
);
|
||||
};
|
||||
|
||||
const handleGameCountdownStartedEvent = function (
|
||||
runtimeScene: gdjs.RuntimeScene
|
||||
) {
|
||||
const handleGameCountdownStartedEvent = function ({
|
||||
runtimeScene,
|
||||
compressionMethod,
|
||||
secondsToStart,
|
||||
}: {
|
||||
runtimeScene: gdjs.RuntimeScene;
|
||||
compressionMethod: gdjs.multiplayerPeerJsHelper.CompressionMethod;
|
||||
secondsToStart: number;
|
||||
}) {
|
||||
gdjs.multiplayerPeerJsHelper.setCompressionMethod(compressionMethod);
|
||||
|
||||
// When the countdown starts, if we are player number 1, then send the peerId to others so they can connect via P2P.
|
||||
if (getCurrentPlayerNumber() === 1) {
|
||||
sendPeerId();
|
||||
@@ -684,6 +714,7 @@ namespace gdjs {
|
||||
lobbiesIframe.contentWindow.postMessage(
|
||||
{
|
||||
id: 'gameCountdownStarted',
|
||||
secondsToStart,
|
||||
},
|
||||
'*' // We could restrict to GDevelop games platform but it's not necessary as the message is not sensitive, and it allows easy debugging.
|
||||
);
|
||||
@@ -698,14 +729,17 @@ namespace gdjs {
|
||||
* When the game receives the information that the game has started, close the
|
||||
* lobbies window, focus on the game, and set the flag to true.
|
||||
*/
|
||||
const handleGameStartedEvent = function (
|
||||
runtimeScene: gdjs.RuntimeScene,
|
||||
heartbeatInterval: number
|
||||
) {
|
||||
const handleGameStartedEvent = function ({
|
||||
runtimeScene,
|
||||
heartbeatInterval,
|
||||
}: {
|
||||
runtimeScene: gdjs.RuntimeScene;
|
||||
heartbeatInterval: number;
|
||||
}) {
|
||||
// It is possible the connection to other players didn't work.
|
||||
// If that's the case, show an error message and leave the lobby.
|
||||
// If we are the host, still start the game, as this allows a player to test the game alone.
|
||||
const allConnectedPeers = gdjs.evtTools.p2p.getAllPeers();
|
||||
const allConnectedPeers = gdjs.multiplayerPeerJsHelper.getAllPeers();
|
||||
if (!isPlayerHost() && allConnectedPeers.length === 0) {
|
||||
gdjs.multiplayerComponents.displayConnectionErrorNotification(
|
||||
runtimeScene
|
||||
@@ -775,7 +809,7 @@ namespace gdjs {
|
||||
}
|
||||
|
||||
// Disconnect from any P2P connections.
|
||||
gdjs.evtTools.p2p.disconnectFromAllPeers();
|
||||
gdjs.multiplayerPeerJsHelper.disconnectFromAllPeers();
|
||||
|
||||
// Clear the expected acknowledgments, as the game is ending.
|
||||
gdjs.multiplayerMessageManager.clearExpectedMessageAcknowledgements();
|
||||
@@ -785,9 +819,9 @@ namespace gdjs {
|
||||
* When the game receives the information of the peerId, then
|
||||
* the player can connect to the peer.
|
||||
*/
|
||||
const handlePeerIdEvent = function (peerId: string) {
|
||||
const handlePeerIdEvent = function ({ peerId }: { peerId: string }) {
|
||||
// When a peerId is received, trigger a P2P connection with the peer.
|
||||
const currentPeerId = gdjs.evtTools.p2p.getCurrentId();
|
||||
const currentPeerId = gdjs.multiplayerPeerJsHelper.getCurrentId();
|
||||
if (!currentPeerId) {
|
||||
logger.error(
|
||||
'No peerId found, the player does not seem connected to the broker server.'
|
||||
@@ -800,7 +834,7 @@ namespace gdjs {
|
||||
return;
|
||||
}
|
||||
|
||||
gdjs.evtTools.p2p.connect(peerId);
|
||||
gdjs.multiplayerPeerJsHelper.connect(peerId);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -862,6 +896,8 @@ namespace gdjs {
|
||||
// Consider the game is ended, so that we don't listen to other players disconnecting.
|
||||
_isLobbyGameRunning = false;
|
||||
|
||||
logger.info('Ending the lobby game.');
|
||||
|
||||
// Inform the players that the game has ended.
|
||||
gdjs.multiplayerMessageManager.sendEndGameMessage();
|
||||
|
||||
@@ -912,7 +948,7 @@ namespace gdjs {
|
||||
return;
|
||||
}
|
||||
|
||||
const peerId = gdjs.evtTools.p2p.getCurrentId();
|
||||
const peerId = gdjs.multiplayerPeerJsHelper.getCurrentId();
|
||||
if (!peerId) {
|
||||
logger.error(
|
||||
"No peerId found, the player doesn't seem connected to the broker server."
|
||||
@@ -1064,7 +1100,7 @@ namespace gdjs {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_isCheckingIfGameIsRegistered || _isWaitingForLoginCallback) {
|
||||
if (_isCheckingIfGameIsRegistered || _isWaitingForLogin) {
|
||||
// The action is called multiple times, let's prevent that.
|
||||
return;
|
||||
}
|
||||
@@ -1089,13 +1125,13 @@ namespace gdjs {
|
||||
const playerId = gdjs.playerAuthentication.getUserId();
|
||||
const playerToken = gdjs.playerAuthentication.getUserToken();
|
||||
if (!playerId || !playerToken) {
|
||||
_isWaitingForLoginCallback = true;
|
||||
_isWaitingForLogin = true;
|
||||
const {
|
||||
status,
|
||||
} = await gdjs.playerAuthentication.openAuthenticationWindow(
|
||||
runtimeScene
|
||||
).promise;
|
||||
_isWaitingForLoginCallback = false;
|
||||
_isWaitingForLogin = false;
|
||||
|
||||
if (status === 'logged') {
|
||||
openLobbiesWindow(runtimeScene);
|
||||
@@ -1207,5 +1243,15 @@ namespace gdjs {
|
||||
const gameCanvas = runtimeScene.getGame().getRenderer().getCanvas();
|
||||
if (gameCanvas) gameCanvas.focus();
|
||||
};
|
||||
|
||||
/**
|
||||
* Action to allow the player to leave the lobby in-game.
|
||||
*/
|
||||
export const leaveGameLobby = async (runtimeScene: gdjs.RuntimeScene) => {
|
||||
// Handle the case where the game has not started yet, so the player is in the lobby.
|
||||
handleLobbyLeaveEvent();
|
||||
// Handle the case where the game has started, so the player is in the game and connected to other players.
|
||||
handleLobbyGameEnded();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
10
Extensions/Multiplayer/peer.js
vendored
Normal file
10
Extensions/Multiplayer/peer.js
vendored
Normal file
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user