Compare commits

..

4 Commits

Author SHA1 Message Date
Davy Hélard
e93e65e7e1 Review changes: alert and parallelism 2022-04-12 14:25:41 +02:00
Davy Hélard
b67e7035bc Rewording of the tip. 2022-04-12 14:25:41 +02:00
Davy Hélard
b0f824f889 Disable slugs fields and add a tip when the user doesn't have a username. 2022-04-12 14:25:41 +02:00
Davy Hélard
ee7065d52c Allow to verify and change the url slug right before publishing a game 2022-04-12 14:22:52 +02:00
956 changed files with 53160 additions and 60699 deletions

View File

@@ -2,17 +2,10 @@
# on the Electron runtime (newIDE/electron-app) for macOS and Linux.
# For Windows, see the appveyor.yml file.
# This also builds GDevelop.js and store it on a S3 so it can be used to run
# GDevelop without building it from scratch.
# Note that these CircleCI builds/tests are not launched on Pull Requests from forks,
# to avoid sharing secrets.
version: 2.1
orbs:
aws-cli: circleci/aws-cli@2.0.6
jobs:
# Build the **entire** app for macOS.
build-macos:
macos:
xcode: 12.5.1
@@ -82,7 +75,6 @@ jobs:
name: Deploy to S3 (latest)
command: export PATH=~/.local/bin:$PATH && aws s3 sync newIDE/electron-app/dist s3://gdevelop-releases/$(git rev-parse --abbrev-ref HEAD)/latest/
# Build the **entire** app for Linux.
build-linux:
# CircleCI docker workers are failing if they don't have enough memory (no swap)
resource_class: xlarge
@@ -161,67 +153,10 @@ jobs:
name: Deploy to S3 (latest)
command: aws s3 sync newIDE/electron-app/dist s3://gdevelop-releases/$(git rev-parse --abbrev-ref HEAD)/latest/
# Build the WebAssembly library only (so that it's cached on a S3 and easy to re-use).
build-gdevelop_js-wasm-only:
docker:
- image: cimg/node:16.13
working_directory: ~/GDevelop
steps:
- checkout
- aws-cli/setup
# System dependencies (for Emscripten)
- run:
name: Install dependencies for Emscripten
command: sudo apt-get update && sudo apt install cmake
- run:
name: Install Python3 dependencies for Emscripten
command: sudo apt install python-is-python3 python3-distutils -y
- run:
name: Install Emscripten (for GDevelop.js)
command: git clone https://github.com/juj/emsdk.git && cd emsdk && ./emsdk install 1.39.6 && ./emsdk activate 1.39.6 && cd ..
# GDevelop.js dependencies
- restore_cache:
keys:
- gdevelop.js-linux-nodejs-dependencies-{{ checksum "GDevelop.js/package-lock.json" }}
# fallback to using the latest cache if no exact match is found
- gdevelop.js-linux-nodejs-dependencies-
- run:
name: Install GDevelop.js dependencies and build it
command: cd GDevelop.js && npm install && cd ..
# Build GDevelop.js (and run tests to ensure it works)
- run:
name: Build GDevelop.js
command: cd GDevelop.js && source ../emsdk/emsdk_env.sh && npm run build && npm test && cd ..
- save_cache:
paths:
- GDevelop.js/node_modules
key: gdevelop.js-linux-nodejs-dependencies-{{ checksum "GDevelop.js/package-lock.json" }}
# Upload artifacts (CircleCI)
- store_artifacts:
path: Binaries/embuild/GDevelop.js
# Upload artifacts (AWS)
- run:
name: Deploy to S3 (specific commit)
command: aws s3 sync Binaries/embuild/GDevelop.js s3://gdevelop-gdevelop.js/$(git rev-parse --abbrev-ref HEAD)/commit/$(git rev-parse HEAD)/
- run:
name: Deploy to S3 (latest)
command: aws s3 sync Binaries/embuild/GDevelop.js s3://gdevelop-gdevelop.js/$(git rev-parse --abbrev-ref HEAD)/latest/
workflows:
builds:
jobs:
- build-gdevelop_js-wasm-only
- build-macos:
filters:
branches:

View File

@@ -12,7 +12,7 @@ jobs:
repo-token: ${{ secrets.GITHUB_TOKEN }}
type: "body"
regex: ".*Scroll down to '\\.\\.\\.\\.'.*"
message: "Hi @${issue.user.login}! 👋 This issue was automatically closed because it seems that you have not included any steps to reproduce the bug.\n\nGitHub is a place for the technical development of GDevelop itself - you may want to go on the [forum](https://forum.gdevelop-app.com/), the Discord chat or [read the documentation](https://wiki.gdevelop.io/gdevelop5/start) to learn more about GDevelop. Thanks!"
message: "Hi @${issue.user.login}! 👋 This issue was automatically closed because it seems that you have not included any steps to reproduce the bug.\n\nGitHub is a place for the technical development of GDevelop itself - you may want to go on the [forum](https://forum.gdevelop-app.com/), the Discord chat or [read the documentation](http://wiki.compilgames.net/doku.php/gdevelop5/start) to learn more about GDevelop. Thanks!"
- name: Autoclose known beta 105 web-app update bug
uses: arkon/issue-closer-action@v1.1
with:

1
.gitignore vendored
View File

@@ -8,7 +8,6 @@
/Binaries/.embuild*
/Binaries/build*
/Binaries/embuild*
/emsdk
*.dll
*.exe
*.a

View File

@@ -1,25 +0,0 @@
# This is a configuration file allowing to quickly set up a development environment
# on GitPod (https://www.gitpod.io/).
# Also check GitHub codespaces if you're interested in working
# on a remote development server.
# This works well for:
# - The editor web-app, including the C++ classes.
# This is not yet adapted for:
# - Working on the game engine or extensions, as they can't be easily tested on the web-app.
# - Working on the desktop app (Electron).
tasks:
- name: Install dependencies for Emscripten and build GDevelop.js
init: |
sudo apt-get update
sudo apt install cmake python-is-python3 python3-distutils -y
git clone https://github.com/juj/emsdk.git && cd emsdk && ./emsdk install 1.39.6 && ./emsdk activate 1.39.6 && cd ..
cd GDevelop.js
npm install
source ../emsdk/emsdk_env.sh && npm run build -- --dev
cd ..
- name: Install GDevelop IDE dependencies
init: cd newIDE/app && npm install && cd ../electron-app && npm install

View File

@@ -1,6 +1,9 @@
# Travis CI configuration to build and run all tests
# (and typing/formatting) for the Core, newIDE, GDJS.
#
# This builds GDevelop.js and store it on a S3 so it can be used to run
# GDevelop without building it.
#
# See also Semaphore CI for quick tests (not building GDevelop.js, so
# faster but not always reliable).
@@ -14,7 +17,18 @@ cache:
directories:
- $HOME/.npm
services:
# Virtual Framebuffer 'fake' X server for SFML
- xvfb
addons:
artifacts:
s3_region: "us-east-1"
target_paths:
- /$(if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then echo $TRAVIS_BRANCH; else echo $TRAVIS_PULL_REQUEST_BRANCH; fi)/commit/$(git rev-parse HEAD)
- /$(if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then echo $TRAVIS_BRANCH; else echo $TRAVIS_PULL_REQUEST_BRANCH; fi)/latest
paths:
- Binaries/embuild/GDevelop.js
apt:
sources:
- ubuntu-toolchain-r-test
@@ -22,8 +36,20 @@ addons:
# Build dependencies:
- cmake
- p7zip-full
# SFML dependencies:
- libopenal-dev
- libjpeg-dev
- libglew-dev
- libudev-dev
- libxrandr-dev
- libsndfile1-dev
- libglu1-mesa-dev
- libfreetype6-dev
before_install:
#Activate X Virtual Framebuffer to allow tests to
#use SFML.
- "export DISPLAY=:99.0"
# This workaround is required to avoid libstdc++ errors (Emscripten requires a recent version of libstdc++)
- wget -q -O libstdc++6 http://security.ubuntu.com/ubuntu/pool/main/g/gcc-5/libstdc++6_5.4.0-6ubuntu1~16.04.12_amd64.deb
- sudo dpkg --force-all -i libstdc++6

View File

@@ -7,9 +7,11 @@
"${workspaceRoot}/GDJS",
"${workspaceRoot}/Extensions",
"${workspaceRoot}/Core",
"${workspaceRoot}/ExtLibs/SFML/include",
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1",
"/usr/local/include",
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include",
"/usr/include",
"${workspaceRoot}"
],
"defines": [
@@ -25,6 +27,7 @@
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1",
"/usr/local/include",
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include",
"/usr/include",
"${workspaceRoot}"
],
"limitSymbolsToIncludedHeaders": true,
@@ -45,6 +48,7 @@
"${workspaceRoot}/GDJS",
"${workspaceRoot}/Extensions",
"${workspaceRoot}/Core",
"${workspaceRoot}/ExtLibs/SFML/include",
"/usr/include",
"/usr/local/include",
"${workspaceRoot}"
@@ -74,6 +78,7 @@
"${workspaceRoot}/GDJS",
"${workspaceRoot}/Extensions",
"${workspaceRoot}/Core",
"${workspaceRoot}/ExtLibs/SFML/include",
"${workspaceRoot}"
],
"defines": [
@@ -96,4 +101,4 @@
}
],
"version": 4
}
}

14
.vscode/launch.json vendored
View File

@@ -15,20 +15,6 @@
"disableOptimisticBPs": true,
"cwd": "${workspaceFolder}/GDevelop.js"
},
{
"type": "node",
"request": "launch",
"name": "newIDE/app Jest tests (current file)",
"program": "${workspaceFolder}/newIDE/app/node_modules/.bin/react-scripts",
"args": [
"test", "--env=node",
"${fileBasenameNoExtension}"
],
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen",
"disableOptimisticBPs": true,
"cwd": "${workspaceFolder}/newIDE/app"
},
{
"type": "node",
"request": "launch",

View File

@@ -115,6 +115,7 @@
"files.exclude": {
"Binaries/*build*": true,
"Binaries/Output": true,
"ExtLibs/SFML": true,
"GDJS/Runtime-dist": true,
"docs": true,
"newIDE/electron-app/dist": true,

View File

@@ -17,7 +17,7 @@ endmacro()
gd_set_option(BUILD_CORE TRUE BOOL "TRUE to build GDevelop Core library")
gd_set_option(BUILD_GDJS TRUE BOOL "TRUE to build GDevelop JS Platform")
gd_set_option(BUILD_EXTENSIONS TRUE BOOL "TRUE to build the extensions")
gd_set_option(BUILD_TESTS TRUE BOOL "TRUE to build the tests")
gd_set_option(BUILD_TESTS FALSE BOOL "TRUE to build the tests")
# Disable deprecated code
set(NO_GUI TRUE CACHE BOOL "" FORCE) #Force disable old GUI related code.

View File

@@ -14,6 +14,7 @@ set(GDCORE_lib_dir ${GD_base_dir}/Binaries/Output/${CMAKE_BUILD_TYPE}_${CMAKE_SY
#Dependencies on external libraries:
###
include_directories(${sfml_include_dir})
#Defines
###
@@ -67,6 +68,14 @@ set(LIBRARY_OUTPUT_PATH ${GD_base_dir}/Binaries/Output/${CMAKE_BUILD_TYPE}_${CMA
set(ARCHIVE_OUTPUT_PATH ${GD_base_dir}/Binaries/Output/${CMAKE_BUILD_TYPE}_${CMAKE_SYSTEM_NAME})
set(RUNTIME_OUTPUT_PATH ${GD_base_dir}/Binaries/Output/${CMAKE_BUILD_TYPE}_${CMAKE_SYSTEM_NAME})
#Linker files
###
IF(EMSCRIPTEN)
#Nothing.
ELSE()
target_link_libraries(GDCore ${sfml_LIBRARIES})
ENDIF()
#Tests
###
if(BUILD_TESTS)
@@ -79,5 +88,5 @@ if(BUILD_TESTS)
add_executable(GDCore_tests ${test_source_files})
set_target_properties(GDCore_tests PROPERTIES BUILD_WITH_INSTALL_RPATH FALSE) #Allow finding dependencies directly from build path on Mac OS X.
target_link_libraries(GDCore_tests GDCore)
target_link_libraries(GDCore_tests ${CMAKE_DL_LIBS})
target_link_libraries(GDCore_tests ${sfml_LIBRARIES})
endif()

View File

@@ -13,6 +13,7 @@
#include <string>
#include <vector>
#include "Utf8/utf8.h"
#include <SFML/System/String.hpp>
#ifdef __GNUC__
#define GD_DEPRECATED __attribute__((deprecated))

View File

@@ -1,36 +0,0 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#include "AsyncEvent.h"
#include "GDCore/CommonTools.h"
#include "GDCore/Events/CodeGeneration/EventsCodeGenerationContext.h"
#include "GDCore/Events/CodeGeneration/EventsCodeGenerator.h"
#include "GDCore/Events/Serialization.h"
#include "GDCore/Serialization/SerializerElement.h"
using namespace std;
namespace gd {
AsyncEvent::AsyncEvent() : BaseEvent() {}
AsyncEvent::~AsyncEvent(){};
vector<const gd::InstructionsList *> AsyncEvent::GetAllActionsVectors() const {
vector<const gd::InstructionsList *> allActions;
allActions.push_back(&actions);
return allActions;
}
vector<gd::InstructionsList *> AsyncEvent::GetAllActionsVectors() {
vector<gd::InstructionsList *> allActions;
allActions.push_back(&actions);
return allActions;
}
} // namespace gd

View File

@@ -1,61 +0,0 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#ifndef GDCORE_ASYNCEVENT_H
#define GDCORE_ASYNCEVENT_H
#include "GDCore/Events/Event.h"
#include "GDCore/Events/EventsList.h"
#include "GDCore/Events/Instruction.h"
#include "GDCore/Events/InstructionsList.h"
namespace gd {
class Instruction;
class Project;
} // namespace gd
namespace gd {
/**
* \brief Internal event for asynchronous actions.
* This event gets added internally to the events tree when an
* asynchronous action is used.
*/
class GD_CORE_API AsyncEvent : public gd::BaseEvent {
public:
AsyncEvent();
AsyncEvent(const gd::Instruction &asyncAction_,
const gd::InstructionsList &actions_,
const gd::EventsList &subEvents_)
: asyncAction(asyncAction_), actions(actions_), subEvents(subEvents_) {
SetType("BuiltinAsync::Async");
};
virtual ~AsyncEvent();
virtual gd::AsyncEvent *Clone() const { return new AsyncEvent(*this); }
virtual bool IsExecutable() const { return true; }
virtual bool CanHaveSubEvents() const { return true; }
virtual const gd::EventsList &GetSubEvents() const { return subEvents; };
virtual gd::EventsList &GetSubEvents() { return subEvents; };
const gd::InstructionsList &GetActions() const { return actions; };
gd::InstructionsList &GetActions() { return actions; };
const gd::Instruction &GetInstruction() const { return asyncAction; };
gd::Instruction &GetInstruction() { return asyncAction; };
virtual std::vector<const gd::InstructionsList *>
GetAllActionsVectors() const;
virtual std::vector<gd::InstructionsList *> GetAllActionsVectors();
private:
gd::Instruction asyncAction;
gd::InstructionsList actions;
EventsList subEvents;
};
} // namespace gd
#endif // GDCORE_STANDARDEVENT_H

View File

@@ -63,12 +63,8 @@ void StandardEvent::UnserializeFrom(gd::Project& project,
project, conditions, element.GetChild("conditions", 0, "Conditions"));
gd::EventsListSerialization::UnserializeInstructionsFrom(
project, actions, element.GetChild("actions", 0, "Actions"));
events.Clear();
if (element.HasChild("events", "Events")) {
gd::EventsListSerialization::UnserializeEventsFrom(
project, events, element.GetChild("events", 0, "Events"));
}
gd::EventsListSerialization::UnserializeEventsFrom(
project, events, element.GetChild("events", 0, "Events"));
}
} // namespace gd

View File

@@ -4,9 +4,7 @@
* reserved. This project is released under the MIT License.
*/
#include "GDCore/Events/CodeGeneration/EventsCodeGenerationContext.h"
#include <set>
#include "GDCore/CommonTools.h"
#include "GDCore/Events/CodeGeneration/EventsCodeGenerator.h"
#include "GDCore/Events/Tools/EventsCodeNameMangler.h"
@@ -16,7 +14,7 @@ using namespace std;
namespace gd {
void EventsCodeGenerationContext::InheritsFrom(
EventsCodeGenerationContext& parent_) {
const EventsCodeGenerationContext& parent_) {
parent = &parent_;
// Objects lists declared by parent became "already declared" in the child
@@ -26,8 +24,8 @@ void EventsCodeGenerationContext::InheritsFrom(
parent_.objectsListsToBeDeclared.end(),
std::inserter(alreadyDeclaredObjectsLists,
alreadyDeclaredObjectsLists.begin()));
std::copy(parent_.objectsListsOrEmptyToBeDeclared.begin(),
parent_.objectsListsOrEmptyToBeDeclared.end(),
std::copy(parent_.objectsListsWithoutPickingToBeDeclared.begin(),
parent_.objectsListsWithoutPickingToBeDeclared.end(),
std::inserter(alreadyDeclaredObjectsLists,
alreadyDeclaredObjectsLists.begin()));
std::copy(parent_.emptyObjectsListsToBeDeclared.begin(),
@@ -35,8 +33,6 @@ void EventsCodeGenerationContext::InheritsFrom(
std::inserter(alreadyDeclaredObjectsLists,
alreadyDeclaredObjectsLists.begin()));
nearestAsyncParent = parent_.IsAsyncCallback() ? &parent_ : parent_.nearestAsyncParent;
asyncDepth = parent_.asyncDepth;
depthOfLastUse = parent_.depthOfLastUse;
customConditionDepth = parent_.customConditionDepth;
contextDepth = parent_.GetContextDepth() + 1;
@@ -46,59 +42,33 @@ void EventsCodeGenerationContext::InheritsFrom(
}
}
void EventsCodeGenerationContext::InheritsAsAsyncCallbackFrom(
EventsCodeGenerationContext& parent_) {
// Increasing the async depth is enough to mark the context as an async callback.
InheritsFrom(parent_);
asyncDepth = parent_.asyncDepth + 1;
}
void EventsCodeGenerationContext::Reuse(
EventsCodeGenerationContext& parent_) {
const EventsCodeGenerationContext& parent_) {
InheritsFrom(parent_);
if (parent_.CanReuse())
contextDepth = parent_.GetContextDepth(); // Keep same context depth
}
void EventsCodeGenerationContext::NotifyAsyncParentsAboutDeclaredObject(const gd::String& objectName) {
gd::EventsCodeGenerationContext* asyncContext = IsAsyncCallback() ? this : nearestAsyncParent;
for (;
asyncContext != nullptr;
asyncContext = asyncContext->parent->nearestAsyncParent)
asyncContext->allObjectsListToBeDeclaredAcrossChildren.insert(objectName);
}
void EventsCodeGenerationContext::ObjectsListNeeded(
const gd::String& objectName) {
if (!IsToBeDeclared(objectName)) {
if (!IsToBeDeclared(objectName))
objectsListsToBeDeclared.insert(objectName);
if (IsInsideAsync()) {
NotifyAsyncParentsAboutDeclaredObject(objectName);
}
}
depthOfLastUse[objectName] = GetContextDepth();
}
void EventsCodeGenerationContext::ObjectsListNeededOrEmptyIfJustDeclared(
void EventsCodeGenerationContext::ObjectsListWithoutPickingNeeded(
const gd::String& objectName) {
if (!IsToBeDeclared(objectName)) {
objectsListsOrEmptyToBeDeclared.insert(objectName);
if (IsInsideAsync()) {
NotifyAsyncParentsAboutDeclaredObject(objectName);
}
}
if (!IsToBeDeclared(objectName))
objectsListsWithoutPickingToBeDeclared.insert(objectName);
depthOfLastUse[objectName] = GetContextDepth();
}
void EventsCodeGenerationContext::EmptyObjectsListNeeded(
const gd::String& objectName) {
if (!IsToBeDeclared(objectName)) {
if (!IsToBeDeclared(objectName))
emptyObjectsListsToBeDeclared.insert(objectName);
}
depthOfLastUse[objectName] = GetContextDepth();
}
@@ -107,8 +77,8 @@ std::set<gd::String> EventsCodeGenerationContext::GetAllObjectsToBeDeclared()
const {
std::set<gd::String> allObjectListsToBeDeclared(
objectsListsToBeDeclared.begin(), objectsListsToBeDeclared.end());
allObjectListsToBeDeclared.insert(objectsListsOrEmptyToBeDeclared.begin(),
objectsListsOrEmptyToBeDeclared.end());
allObjectListsToBeDeclared.insert(objectsListsWithoutPickingToBeDeclared.begin(),
objectsListsWithoutPickingToBeDeclared.end());
allObjectListsToBeDeclared.insert(emptyObjectsListsToBeDeclared.begin(),
emptyObjectsListsToBeDeclared.end());
@@ -132,21 +102,4 @@ bool EventsCodeGenerationContext::IsSameObjectsList(
otherContext.GetLastDepthObjectListWasNeeded(objectName);
}
bool EventsCodeGenerationContext::ShouldUseAsyncObjectsList(
const gd::String& objectName) const {
if (!IsInsideAsync()) return false;
// Check if the objects list was used after (or in) the nearest async callback context.
const gd::EventsCodeGenerationContext* asyncContext = IsAsyncCallback() ? this : nearestAsyncParent;
if (parent->GetLastDepthObjectListWasNeeded(objectName) >= asyncContext->GetContextDepth()) {
// The object was used in a context after (or in) the nearest async parent context, so we're not getting it from the
// async object lists (it was already gotten from there in this previous context).
return false;
}
// If the objects list is declared in a parent of the nearest async context, it means
// the async context had to use an async objects list to access it.
return asyncContext->ObjectAlreadyDeclaredByParents(objectName);
};
} // namespace gd

View File

@@ -8,7 +8,6 @@
#include <map>
#include <memory>
#include <set>
#include "GDCore/String.h"
namespace gd {
@@ -34,7 +33,11 @@ class GD_CORE_API EventsCodeGenerationContext {
* updated to contain the maximal scope depth reached.
*/
EventsCodeGenerationContext(unsigned int* maxDepthLevel_ = nullptr)
: maxDepthLevel(maxDepthLevel_){};
: contextDepth(0),
customConditionDepth(0),
maxDepthLevel(maxDepthLevel_),
parent(NULL),
reuseExplicitlyForbidden(false){};
virtual ~EventsCodeGenerationContext(){};
/**
@@ -42,13 +45,7 @@ class GD_CORE_API EventsCodeGenerationContext {
* another one. The child will then for example not declare again objects
* already declared by its parent.
*/
void InheritsFrom(EventsCodeGenerationContext& parent);
/**
* Call this method to make an EventsCodeGenerationContext as a "child" of
* another one, but in the context of an async function.
*/
void InheritsAsAsyncCallbackFrom(EventsCodeGenerationContext& parent);
void InheritsFrom(const EventsCodeGenerationContext& parent);
/**
* \brief As InheritsFrom, mark the context as being the child of another one,
@@ -56,7 +53,7 @@ class GD_CORE_API EventsCodeGenerationContext {
*
* Used for example for optimizing the last event of a list.
*/
void Reuse(EventsCodeGenerationContext& parent);
void Reuse(const EventsCodeGenerationContext& parent);
/**
* \brief Forbid any optimization that would reuse and modify the object list
@@ -91,19 +88,19 @@ class GD_CORE_API EventsCodeGenerationContext {
const EventsCodeGenerationContext* GetParentContext() const { return parent; }
/**
* Mark the object as being the object being handled by the instruction.
* Mark the object has being the object being handled by the instruction
*/
void SetCurrentObject(const gd::String& objectName) {
currentObject = objectName;
};
/**
* Set that no particular object is being handled by an instruction.
* Set that no particular object is being handled by an instruction
*/
void SetNoCurrentObject() { currentObject = ""; };
/**
* Get the object being handled by the instruction.
* Get the object being handled by the instruction
*/
const gd::String& GetCurrentObject() const { return currentObject; };
@@ -112,7 +109,7 @@ class GD_CORE_API EventsCodeGenerationContext {
*
* The list will be filled with objects from the scene if it is the first time
* it is requested, unless there is already an object list with this name
* (i.e. `ObjectAlreadyDeclaredByParents(objectName)` returns true).
* (i.e. `ObjectAlreadyDeclared(objectName)` returns true).
*/
void ObjectsListNeeded(const gd::String& objectName);
@@ -124,7 +121,7 @@ class GD_CORE_API EventsCodeGenerationContext {
* from the scene. If there is already an objects list with this name, no new
* list will be declared again.
*/
void ObjectsListNeededOrEmptyIfJustDeclared(const gd::String& objectName);
void ObjectsListWithoutPickingNeeded(const gd::String& objectName);
/**
* Call this when an instruction in the event needs an empty object list,
@@ -137,21 +134,29 @@ class GD_CORE_API EventsCodeGenerationContext {
void EmptyObjectsListNeeded(const gd::String& objectName);
/**
* Return true if an object list has already been declared by the parent contexts.
* Return true if an object list has already been declared (or is going to be
* declared).
*/
bool ObjectAlreadyDeclaredByParents(const gd::String& objectName) const {
bool ObjectAlreadyDeclared(const gd::String& objectName) const {
return (alreadyDeclaredObjectsLists.find(objectName) !=
alreadyDeclaredObjectsLists.end());
};
/**
* \brief Consider that \a objectName is now declared in the context.
*/
void SetObjectDeclared(const gd::String& objectName) {
alreadyDeclaredObjectsLists.insert(objectName);
}
/**
* Return all the objects lists which will be declared by the current context
* (normal, potentially empty or empty).
* ( the non empty as well as the empty objects lists )
*/
std::set<gd::String> GetAllObjectsToBeDeclared() const;
/**
* Return the objects lists which will be declared by the current context.
* Return the objects lists which will be declared by the current context
*/
const std::set<gd::String>& GetObjectsListsToBeDeclared() const {
return objectsListsToBeDeclared;
@@ -161,9 +166,9 @@ class GD_CORE_API EventsCodeGenerationContext {
* Return the objects lists which will be will be declared, without filling
* them with objects from the scene.
*/
const std::set<gd::String>& GetObjectsListsToBeEmptyIfJustDeclared()
const std::set<gd::String>& GetObjectsListsToBeDeclaredWithoutPicking()
const {
return objectsListsOrEmptyToBeDeclared;
return objectsListsWithoutPickingToBeDeclared;
};
/**
@@ -179,7 +184,7 @@ class GD_CORE_API EventsCodeGenerationContext {
* Return the objects lists which are already declared and can be used in the
* current context without declaration.
*/
const std::set<gd::String>& GetObjectsListsAlreadyDeclaredByParents() const {
const std::set<gd::String>& GetObjectsListsAlreadyDeclared() const {
return alreadyDeclaredObjectsLists;
};
@@ -222,55 +227,22 @@ class GD_CORE_API EventsCodeGenerationContext {
*/
size_t GetCurrentConditionDepth() const { return customConditionDepth; }
/**
* \brief Returns the list of all objects declared in this context
* and subcontexts.
* \warning Only works on an async callback's context.
*
* It is to be used by the Async event code generator to know what objects
* lists to backup for the async callback and async callbacks after it.
*/
const std::set<gd::String>& GetAllDeclaredObjectsAcrossChildren() {
return allObjectsListToBeDeclaredAcrossChildren;
};
/**
* Returns true if an object list should be gotten from a backed up
* objects list instead of the parent context. This can happen inside an
* asynchronous callback or a child context of an asynchronous callback (i.e:
* the `asyncDepth` is not 0).
*/
bool ShouldUseAsyncObjectsList(const gd::String& objectName) const;
/**
* Returns true if the code currently being generated is inside an
* asynchronous context (either in an asynchronous callback, or in a children of
* an asynchronous callback).
*/
bool IsInsideAsync() const { return asyncDepth != 0; };
/**
* Returns true if the code currently being generated is an asynchronous
* callback (but not a child of an asynchronous callback).
*/
bool IsAsyncCallback() const { return parent != nullptr && parent->asyncDepth != asyncDepth; }
private:
/**
* \brief Returns true if the given object is already going to be declared
* in this context (either as a traditional objects list, or an empty one).
* (either as a traditional objects list, or one without picking, or one
* empty).
*
*/
bool IsToBeDeclared(const gd::String& objectName) {
return objectsListsToBeDeclared.find(objectName) !=
objectsListsToBeDeclared.end() ||
objectsListsOrEmptyToBeDeclared.find(objectName) !=
objectsListsOrEmptyToBeDeclared.end() ||
objectsListsWithoutPickingToBeDeclared.find(objectName) !=
objectsListsWithoutPickingToBeDeclared.end() ||
emptyObjectsListsToBeDeclared.find(objectName) !=
emptyObjectsListsToBeDeclared.end();
};
private:
void NotifyAsyncParentsAboutDeclaredObject(const gd::String& objectName);
std::set<gd::String>
alreadyDeclaredObjectsLists; ///< Objects lists already needed in a
///< parent context.
@@ -278,7 +250,7 @@ class GD_CORE_API EventsCodeGenerationContext {
objectsListsToBeDeclared; ///< Objects lists that will be declared in
///< this context.
std::set<gd::String>
objectsListsOrEmptyToBeDeclared; ///< Objects lists that will be
objectsListsWithoutPickingToBeDeclared; ///< Objects lists that will be
///< declared in this context,
///< but not filled with scene's
///< objects.
@@ -288,40 +260,21 @@ class GD_CORE_API EventsCodeGenerationContext {
///< but not filled with scene's
///< objects and not filled with any
///< previously existing objects list.
std::set<gd::String>
allObjectsListToBeDeclaredAcrossChildren; ///< This is only to be used by
///< the async callback
///< contexts to know all
///< objects declared across
///< all children, so that the
///< necessary objects can be
///< backed up.
std::map<gd::String, unsigned int>
depthOfLastUse; ///< The context depth when an object was last used.
gd::String
currentObject; ///< The object being used by an action or condition.
unsigned int contextDepth = 0; ///< The depth of the context: 0 for a newly
///< created context, n+1 for any context
///< inheriting from context with depth n.
unsigned int customConditionDepth =
0; ///< The depth of the conditions being generated.
unsigned int asyncDepth =
0; ///< If higher than 0, the current context is an asynchronous callback,
///< or a child context of an asynchronous callback:
///< - If the parent's async depth != the current context async depth,
///< then the current context is an asynchronous callback context.
///< - Otherwise, it's a child of an asynchronous callback.
unsigned int contextDepth; ///< The depth of the context : 0 for a newly
///< created context, n+1 for any context
///< inheriting from context with depth n.
unsigned int
customConditionDepth; ///< The depth of the conditions being generated.
unsigned int* maxDepthLevel; ///< A pointer to a unsigned int updated with
///< the maximum depth reached.
const EventsCodeGenerationContext* parent =
nullptr; ///< The parent of the current context. Can be NULL.
EventsCodeGenerationContext* nearestAsyncParent =
nullptr; ///< The nearest parent context that is an async callback
///< context.
bool reuseExplicitlyForbidden =
false; ///< If set to true, forbid children contexts
///< to reuse this one without inheriting.
const EventsCodeGenerationContext*
parent; ///< The parent of the current context. Can be NULL.
bool reuseExplicitlyForbidden; ///< If set to true, forbid children context
///< to reuse this one without inheriting.
};
} // namespace gd

View File

@@ -450,9 +450,7 @@ gd::String EventsCodeGenerator::GenerateConditionsListCode(
* Generate code for an action.
*/
gd::String EventsCodeGenerator::GenerateActionCode(
gd::Instruction& action,
EventsCodeGenerationContext& context,
const gd::String& optionalAsyncCallbackName) {
gd::Instruction& action, EventsCodeGenerationContext& context) {
gd::String actionCode;
const gd::InstructionMetadata& instrInfos =
@@ -520,12 +518,8 @@ gd::String EventsCodeGenerator::GenerateActionCode(
// Prepare arguments and generate the whole action code
vector<gd::String> arguments = GenerateParametersCodes(
action.GetParameters(), instrInfos.parameters, context);
actionCode += GenerateObjectAction(realObjects[i],
objInfo,
arguments,
instrInfos,
context,
optionalAsyncCallbackName);
actionCode += GenerateObjectAction(
realObjects[i], objInfo, arguments, instrInfos, context);
context.SetNoCurrentObject();
}
@@ -558,8 +552,7 @@ gd::String EventsCodeGenerator::GenerateActionCode(
autoInfo,
arguments,
instrInfos,
context,
optionalAsyncCallbackName);
context);
context.SetNoCurrentObject();
}
@@ -567,72 +560,12 @@ gd::String EventsCodeGenerator::GenerateActionCode(
} else {
vector<gd::String> arguments = GenerateParametersCodes(
action.GetParameters(), instrInfos.parameters, context);
actionCode +=
GenerateFreeAction(arguments, instrInfos, context, optionalAsyncCallbackName);
actionCode += GenerateFreeAction(arguments, instrInfos, context);
}
return actionCode;
}
const EventsCodeGenerator::CallbackDescriptor
EventsCodeGenerator::GenerateCallback(
const gd::String& callbackID,
gd::EventsCodeGenerationContext& parentContext,
gd::InstructionsList& actions,
gd::EventsList* subEvents) {
gd::EventsCodeGenerationContext callbackContext;
callbackContext.InheritsAsAsyncCallbackFrom(parentContext);
const gd::String callbackFunctionName =
GetCodeNamespaceAccessor() + "asyncCallback" + callbackID;
const gd::String callbackFunctionArguments =
GenerateEventsParameters(callbackContext);
// Generate actions
gd::String actionsCode = GenerateActionsListCode(actions, callbackContext);
// Generate subevents
if (subEvents != nullptr) // Sub events
{
actionsCode += "\n{ //Subevents\n";
actionsCode += GenerateEventsListCode(*subEvents, callbackContext);
actionsCode += "} //End of subevents\n";
}
// Compose the callback function and add outside main
const gd::String actionsDeclarationsCode =
GenerateObjectsDeclarationCode(callbackContext);
const gd::String callbackCode = callbackFunctionName + " = function (" +
GenerateEventsParameters(callbackContext) +
") {\n" + actionsDeclarationsCode +
actionsCode + "}\n";
AddCustomCodeOutsideMain(callbackCode);
std::set<gd::String> requiredObjects;
// Build the list of all objects required by the callback. Any object that has
// already been declared could have gone through previous object picking, so
// if such an object is used by the actions or subevents of this callback, we
// must ask the caller to pass the already existing objects lists through a
// `LongLivedObjectsList` to the callback function.
for (const auto& objectUsedInSubTree :
callbackContext.GetAllDeclaredObjectsAcrossChildren()) {
if (callbackContext.ObjectAlreadyDeclaredByParents(objectUsedInSubTree))
requiredObjects.insert(objectUsedInSubTree);
};
return CallbackDescriptor(
callbackFunctionName, callbackFunctionArguments, requiredObjects);
};
const gd::String EventsCodeGenerator::GenerateEventsParameters(
const gd::EventsCodeGenerationContext& context) {
gd::String parameters = "runtimeScene";
if (!HasProjectAndLayout()) parameters += ", eventsFunctionContext";
if (context.IsInsideAsync()) parameters += ", asyncObjectsList";
return parameters;
};
/**
* Generate actions code.
*/
@@ -810,21 +743,23 @@ gd::String EventsCodeGenerator::GenerateObjectsDeclarationCode(
gd::String declarationsCode;
for (auto object : context.GetObjectsListsToBeDeclared()) {
gd::String objectListDeclaration = "";
if (!context.ObjectAlreadyDeclaredByParents(object)) {
if (!context.ObjectAlreadyDeclared(object)) {
objectListDeclaration = "std::vector<RuntimeObject*> " +
GetObjectListName(object, context) +
" = runtimeContext->GetObjectsRawPointers(\"" +
ConvertToString(object) + "\");\n";
context.SetObjectDeclared(object);
} else
objectListDeclaration = declareObjectList(object, context);
declarationsCode += objectListDeclaration + "\n";
}
for (auto object : context.GetObjectsListsToBeEmptyIfJustDeclared()) {
for (auto object : context.GetObjectsListsToBeDeclaredWithoutPicking()) {
gd::String objectListDeclaration = "";
if (!context.ObjectAlreadyDeclaredByParents(object)) {
if (!context.ObjectAlreadyDeclared(object)) {
objectListDeclaration = "std::vector<RuntimeObject*> " +
GetObjectListName(object, context) + ";\n";
context.SetObjectDeclared(object);
} else
objectListDeclaration = declareObjectList(object, context);
@@ -832,9 +767,10 @@ gd::String EventsCodeGenerator::GenerateObjectsDeclarationCode(
}
for (auto object : context.GetObjectsListsToBeDeclaredEmpty()) {
gd::String objectListDeclaration = "";
if (!context.ObjectAlreadyDeclaredByParents(object)) {
if (!context.ObjectAlreadyDeclared(object)) {
objectListDeclaration = "std::vector<RuntimeObject*> " +
GetObjectListName(object, context) + ";\n";
context.SetObjectDeclared(object);
} else
objectListDeclaration = "std::vector<RuntimeObject*> " +
GetObjectListName(object, context) + ";\n";
@@ -849,7 +785,7 @@ gd::String EventsCodeGenerator::GenerateObjectsDeclarationCode(
* Generate events list code.
*/
gd::String EventsCodeGenerator::GenerateEventsListCode(
gd::EventsList& events, EventsCodeGenerationContext& parentContext) {
gd::EventsList& events, const EventsCodeGenerationContext& parentContext) {
gd::String output;
for (std::size_t eId = 0; eId < events.size(); ++eId) {
// Each event has its own context : Objects picked in an event are totally
@@ -865,8 +801,6 @@ gd::String EventsCodeGenerator::GenerateEventsListCode(
// operation.
bool reuseParentContext =
parentContext.CanReuse() && eId == events.size() - 1;
// TODO: avoid creating if useless.
gd::EventsCodeGenerationContext reusedContext;
reusedContext.Reuse(parentContext);
@@ -1081,8 +1015,7 @@ gd::String EventsCodeGenerator::GenerateBehaviorCondition(
gd::String EventsCodeGenerator::GenerateFreeAction(
const std::vector<gd::String>& arguments,
const gd::InstructionMetadata& instrInfos,
gd::EventsCodeGenerationContext& context,
const gd::String& optionalAsyncCallbackName) {
gd::EventsCodeGenerationContext& context) {
// Generate call
gd::String call;
if (instrInfos.codeExtraInformation.type == "number" ||
@@ -1109,11 +1042,6 @@ gd::String EventsCodeGenerator::GenerateFreeAction(
call = instrInfos.codeExtraInformation.functionCallName + "(" +
GenerateArgumentsList(arguments) + ")";
}
if (!optionalAsyncCallbackName.empty())
call = "runtimeScene.getAsyncTasksManager().addTask(" + call + ", " +
optionalAsyncCallbackName + ")";
return call + ";\n";
}
@@ -1122,8 +1050,7 @@ gd::String EventsCodeGenerator::GenerateObjectAction(
const gd::ObjectMetadata& objInfo,
const std::vector<gd::String>& arguments,
const gd::InstructionMetadata& instrInfos,
gd::EventsCodeGenerationContext& context,
const gd::String& optionalAsyncCallbackName) {
gd::EventsCodeGenerationContext& context) {
// Create call
gd::String call;
if ((instrInfos.codeExtraInformation.type == "number" ||
@@ -1150,11 +1077,8 @@ gd::String EventsCodeGenerator::GenerateObjectAction(
call = instrInfos.codeExtraInformation.functionCallName + "(" +
argumentsStr + ")";
return "For each picked object \"" + objectName + "\", call " + call + "(" +
argumentsStr + ")" +
(optionalAsyncCallbackName.empty() ? "" : (", then call" + optionalAsyncCallbackName)) +
".\n";
argumentsStr + ").\n";
}
}
@@ -1164,8 +1088,7 @@ gd::String EventsCodeGenerator::GenerateBehaviorAction(
const gd::BehaviorMetadata& autoInfo,
const std::vector<gd::String>& arguments,
const gd::InstructionMetadata& instrInfos,
gd::EventsCodeGenerationContext& context,
const gd::String& optionalAsyncCallbackName) {
gd::EventsCodeGenerationContext& context) {
// Create call
gd::String call;
if ((instrInfos.codeExtraInformation.type == "number" ||
@@ -1191,11 +1114,8 @@ gd::String EventsCodeGenerator::GenerateBehaviorAction(
call = instrInfos.codeExtraInformation.functionCallName + "(" +
argumentsStr + ")";
return "For each picked object \"" + objectName + "\", call " + call + "(" +
argumentsStr + ")" + " for behavior \"" + behaviorName + "\"" +
(optionalAsyncCallbackName.empty() ? "" : (", then call" + optionalAsyncCallbackName)) +
".\n";
argumentsStr + ")" + " for behavior \"" + behaviorName + "\".\n";
}
}

View File

@@ -77,7 +77,7 @@ class GD_CORE_API EventsCodeGenerator {
* \return Code
*/
virtual gd::String GenerateEventsListCode(
gd::EventsList& events, EventsCodeGenerationContext& context);
gd::EventsList& events, const EventsCodeGenerationContext& context);
/**
* \brief Generate code for executing a condition list
@@ -155,51 +155,7 @@ class GD_CORE_API EventsCodeGenerator {
* \return Code
*/
gd::String GenerateActionCode(gd::Instruction& action,
EventsCodeGenerationContext& context,
const gd::String& optionalAsyncCallbackName = "");
struct CallbackDescriptor {
CallbackDescriptor(const gd::String functionName_,
const gd::String argumentsList_,
const std::set<gd::String> requiredObjects_)
: functionName(functionName_),
argumentsList(argumentsList_),
requiredObjects(requiredObjects_){};
/**
* The name by which the function can be invoked.
*/
const gd::String functionName;
/**
* The comma separated list of arguments that the function takes.
*/
const gd::String argumentsList;
/**
* A set of all objects that need to be backed up to be passed to the callback code.
*/
const std::set<gd::String> requiredObjects;
};
/**
* \brief Generates actions and events as a callback.
*
* This is used by asynchronous functions to run the code out of the normal
* events flow.
*
* \returns A set with all objects required by the callback code.
* The caller must take care of backing them up in a LongLivedObjectsList,
* and to pass it to the callback function as the last argument.
*/
virtual const CallbackDescriptor GenerateCallback(
const gd::String& callbackFunctionName,
gd::EventsCodeGenerationContext& parentContext,
gd::InstructionsList& actions,
gd::EventsList* subEvents = nullptr);
/**
* \brief Generates the parameters list of an event's generated function.
*/
const gd::String GenerateEventsParameters(
const gd::EventsCodeGenerationContext& context);
EventsCodeGenerationContext& context);
/**
* \brief Generate code for declaring objects lists.
@@ -506,10 +462,17 @@ class GD_CORE_API EventsCodeGenerator {
* Other standard parameters type that should be implemented by platforms:
* - currentScene: Reference to the current runtime scene.
* - objectList : a map containing lists of objects which are specified by the
object name in another parameter.
* - objectListOrEmptyIfJustDeclared : Same as `objectList` but do not pick object if
object name in another parameter. Example:
* \code
AddExpression("Count", _("Object count"), _("Count the number of picked
objects"), _("Objects"), "res/conditions/nbObjet.png")
.AddParameter("objectList", _("Object"))
.SetFunctionName("getPickedObjectsCount");
* \endcode
* - objectListWithoutPicking : Same as objectList but do not pick object if
they are not already picked.
* - objectPtr: Return a reference to the object specified by the object name in
* - objectPtr : Return a reference to the object specified by the object name in
another parameter. Example:
* \code
.AddParameter("object", _("Object"))
@@ -702,16 +665,14 @@ class GD_CORE_API EventsCodeGenerator {
virtual gd::String GenerateFreeAction(
const std::vector<gd::String>& arguments,
const gd::InstructionMetadata& instrInfos,
gd::EventsCodeGenerationContext& context,
const gd::String& optionalAsyncCallbackName = "");
gd::EventsCodeGenerationContext& context);
virtual gd::String GenerateObjectAction(
const gd::String& objectName,
const gd::ObjectMetadata& objInfo,
const std::vector<gd::String>& arguments,
const gd::InstructionMetadata& instrInfos,
gd::EventsCodeGenerationContext& context,
const gd::String& optionalAsyncCallbackName = "");
gd::EventsCodeGenerationContext& context);
virtual gd::String GenerateBehaviorAction(
const gd::String& objectName,
@@ -719,8 +680,7 @@ class GD_CORE_API EventsCodeGenerator {
const gd::BehaviorMetadata& autoInfo,
const std::vector<gd::String>& arguments,
const gd::InstructionMetadata& instrInfos,
gd::EventsCodeGenerationContext& context,
const gd::String& optionalAsyncCallbackName = "");
gd::EventsCodeGenerationContext& context);
gd::String GenerateRelationalOperatorCall(
const gd::InstructionMetadata& instrInfos,

View File

@@ -5,11 +5,8 @@
*/
#include "GDCore/Events/Event.h"
#include "GDCore/Events/Builtin/AsyncEvent.h"
#include "GDCore/Events/CodeGeneration/EventsCodeGenerator.h"
#include "GDCore/Events/EventsList.h"
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
#include "GDCore/Extensions/Platform.h"
#include "GDCore/Extensions/PlatformExtension.h"
@@ -68,40 +65,10 @@ gd::String BaseEvent::GenerateEventCode(
return "";
}
void BaseEvent::PreprocessAsyncActions(const gd::Platform& platform) {
if (!CanHaveSubEvents()) return;
for (const auto& actionsList : GetAllActionsVectors())
for (std::size_t aId = 0; aId < actionsList->size(); ++aId) {
const auto& action = actionsList->at(aId);
const gd::InstructionMetadata& actionMetadata =
gd::MetadataProvider::GetActionMetadata(platform, action.GetType());
if (actionMetadata.IsAsync()) {
gd::InstructionsList remainingActions;
remainingActions.InsertInstructions(
*actionsList, aId + 1, actionsList->size() - 1);
gd::AsyncEvent asyncEvent(action, remainingActions, GetSubEvents());
// Ensure that the local event no longer has any of the actions/subevent
// after the async function
actionsList->RemoveAfter(aId);
GetSubEvents().Clear();
GetSubEvents().InsertEvent(asyncEvent);
// We just moved all the rest, there's nothing left to do in this event.
return;
}
}
};
void BaseEvent::Preprocess(gd::EventsCodeGenerator& codeGenerator,
gd::EventsList& eventList,
std::size_t indexOfTheEventInThisList) {
if (IsDisabled()) return;
PreprocessAsyncActions(codeGenerator.GetPlatform());
if (!MustBePreprocessed()) return;
if (IsDisabled() || !MustBePreprocessed()) return;
try {
if (type.empty()) return;

View File

@@ -10,7 +10,6 @@
#include <iostream>
#include <memory>
#include <vector>
#include "GDCore/Events/Instruction.h"
#include "GDCore/Events/InstructionsList.h"
#include "GDCore/Extensions/Metadata/InstructionMetadata.h"
@@ -24,7 +23,7 @@ class EventsCodeGenerationContext;
class Platform;
class SerializerElement;
class Instruction;
} // namespace gd
}
namespace gd {
@@ -137,15 +136,13 @@ class GD_CORE_API BaseEvent {
* \note Used to preprocess or search in the expressions of the event.
*/
virtual std::vector<std::pair<gd::Expression*, gd::ParameterMetadata> >
GetAllExpressionsWithMetadata() {
GetAllExpressionsWithMetadata() {
std::vector<std::pair<gd::Expression*, gd::ParameterMetadata> > noExpr;
return noExpr;
};
virtual std::vector<
std::pair<const gd::Expression*, const gd::ParameterMetadata> >
GetAllExpressionsWithMetadata() const {
std::vector<std::pair<const gd::Expression*, const gd::ParameterMetadata> >
noExpr;
virtual std::vector<std::pair<const gd::Expression*, const gd::ParameterMetadata> >
GetAllExpressionsWithMetadata() const {
std::vector<std::pair<const gd::Expression*, const gd::ParameterMetadata> > noExpr;
return noExpr;
};
@@ -209,11 +206,6 @@ class GD_CORE_API BaseEvent {
gd::EventsList& eventList,
std::size_t indexOfTheEventInThisList);
/**
* A function that turns all async member actions into an Async subevent for code generation.
*/
void PreprocessAsyncActions(const gd::Platform& platform);
/**
* \brief If MustBePreprocessed is redefined to return true, the
* gd::EventMetadata::preprocessing associated to the event will be called to

View File

@@ -5,7 +5,6 @@
*/
#include "InstructionsList.h"
#include "GDCore/Events/Instruction.h"
#include "GDCore/Project/Project.h"
#include "Serialization.h"
@@ -32,10 +31,6 @@ void InstructionsList::InsertInstructions(const InstructionsList& list,
}
}
void InstructionsList::RemoveAfter(const size_t position) {
elements.resize(position);
}
void InstructionsList::SerializeTo(SerializerElement& element) const {
EventsListSerialization::SerializeInstructionsTo(*this, element);
}

View File

@@ -6,10 +6,9 @@
#ifndef GDCORE_INSTRUCTIONSLIST_H
#define GDCORE_INSTRUCTIONSLIST_H
#include "GDCore/Tools/SPtrList.h"
#include <memory>
#include <vector>
#include "GDCore/Tools/SPtrList.h"
namespace gd {
class Instruction;
}
@@ -23,11 +22,11 @@ class SerializerElement;
namespace gd {
class InstructionsList : public SPtrList<gd::Instruction> {
public:
void InsertInstructions(const InstructionsList &list, size_t begin,
size_t end, size_t position = (size_t)-1);
void RemoveAfter(size_t position);
public:
void InsertInstructions(const InstructionsList& list,
size_t begin,
size_t end,
size_t position = (size_t)-1);
/** \name Serialization
*/
@@ -36,17 +35,17 @@ public:
* \brief Serialize the instructions to the specified element
* \see EventsListSerialization
*/
void SerializeTo(gd::SerializerElement &element) const;
void SerializeTo(gd::SerializerElement& element) const;
/**
* \brief Load the instructions from the specified element
* \see EventsListSerialization
*/
void UnserializeFrom(gd::Project &project,
const gd::SerializerElement &element);
void UnserializeFrom(gd::Project& project,
const gd::SerializerElement& element);
///@}
};
} // namespace gd
} // namespace gd
#endif

View File

@@ -218,8 +218,8 @@ void EventsListSerialization::UnserializeEventsFrom(
event = std::make_shared<EmptyEvent>();
}
event->SetDisabled(eventElem.GetBoolAttribute("disabled", false));
event->SetFolded(eventElem.GetBoolAttribute("folded", false));
event->SetDisabled(eventElem.GetBoolAttribute("disabled"));
event->SetFolded(eventElem.GetBoolAttribute("folded"));
list.InsertEvent(event, list.GetEventsCount());
}
@@ -232,8 +232,8 @@ void EventsListSerialization::SerializeEventsTo(const EventsList& list,
const gd::BaseEvent& event = list.GetEvent(j);
SerializerElement& eventElem = events.AddChild("event");
if (event.IsDisabled()) eventElem.SetAttribute("disabled", event.IsDisabled());
if (event.IsFolded()) eventElem.SetAttribute("folded", event.IsFolded());
eventElem.SetAttribute("disabled", event.IsDisabled());
eventElem.SetAttribute("folded", event.IsFolded());
eventElem.AddChild("type").SetValue(event.GetType());
event.SerializeTo(eventElem);

View File

@@ -42,7 +42,6 @@ class GD_CORE_API BuiltinExtensionsImplementer {
static void ImplementsTimeExtension(gd::PlatformExtension& extension);
static void ImplementsVariablesExtension(gd::PlatformExtension& extension);
static void ImplementsWindowExtension(gd::PlatformExtension& extension);
static void ImplementsAsyncExtension(gd::PlatformExtension& extension);
};
} // namespace gd

View File

@@ -1,32 +0,0 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#include "AllBuiltinExtensions.h"
#include "GDCore/Events/Builtin/AsyncEvent.h"
#include "GDCore/Tools/Localization.h"
using namespace std;
namespace gd {
void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAsyncExtension(
gd::PlatformExtension &extension) {
extension
.SetExtensionInformation(
"BuiltinAsync",
_("Async functions"),
_("Functions that defer the execution of the events after it."),
"Arthur Pacaud (arthuro555)",
"Open source (MIT License)")
.SetCategory("Advanced");
extension.AddEvent("Async",
_("Async event"),
_("Internal event for asynchronous actions"),
"",
"res/eventaddicon.png",
std::make_shared<gd::AsyncEvent>());
}
} // namespace gd

View File

@@ -343,34 +343,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
"res/actions/music.png")
.AddCodeOnlyParameter("currentScene", "")
.MarkAsComplex();
extension
.AddAction(
"FadeSoundVolume",
_("Fade the volume of a sound played on a channel."),
_("Fade the volume of a sound played on a channel to the specified volume within the specified duration."),
_("Fade the sound on channel _PARAM1_ to volume _PARAM2_ within _PARAM3_ seconds"),
_("Sounds on channels"),
"res/actions/son24.png",
"res/actions/son.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier"))
.AddParameter("expression", _("Final volume (0-100)"))
.AddParameter("expression", _("Fading time in seconds"))
.MarkAsAdvanced();
extension
.AddAction(
"FadeMusicVolume",
_("Fade the volume of a music played on a channel."),
_("Fade the volume of a music played on a channel to the specified volume within the specified duration."),
_("Fade the music on channel _PARAM1_ to volume _PARAM2_ within _PARAM3_ seconds"),
_("Music on channels"),
"res/actions/music24.png",
"res/actions/music.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier"))
.AddParameter("expression", _("Final volume (0-100)"))
.AddParameter("expression", _("Fading time in seconds"))
.MarkAsAdvanced();
extension
.AddCondition("MusicPlaying",

View File

@@ -1252,7 +1252,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/actions/create24.png",
"res/actions/create24.png")
.AddCodeOnlyParameter("objectsContext", "")
.AddParameter("objectListOrEmptyIfJustDeclared", _("Object to create"))
.AddParameter("objectListWithoutPicking", _("Object to create"))
.AddParameter("expression", _("X position"))
.AddParameter("expression", _("Y position"))
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
@@ -1270,7 +1270,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/actions/create24.png",
"res/actions/create24.png")
.AddCodeOnlyParameter("objectsContext", "")
.AddParameter("objectListOrEmptyIfJustDeclared", _("Group of potential objects"))
.AddParameter("objectListWithoutPicking", _("Group of potential objects"))
.SetParameterLongDescription(
_("Group containing objects that can be created by the action."))
.AddParameter("string", _("Name of the object to create"))
@@ -1418,33 +1418,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/conditions/nbObjet.png")
.AddParameter("objectList", _("Object"))
.UseStandardRelationalOperatorParameters("number")
.MarkAsSimple()
.SetHidden();
extension.AddExpressionAndCondition(
"number",
"SceneInstancesCount",
_("Number of object instances on the scene"),
_("the number of instances of the specified objects living on the scene"),
_("the number of _PARAM1_ living on the scene"),
_("Objects"),
"res/conditions/nbObjet24.png")
.AddCodeOnlyParameter("objectsContext", "")
.AddParameter("objectListOrEmptyWithoutPicking", _("Object"))
.UseStandardParameters("number")
.MarkAsSimple();
extension.AddExpressionAndCondition(
"number",
"PickedInstancesCount",
_("Number of object instances currently picked"),
_("the number of instances picked by the previous conditions (or actions)"),
_("the number of _PARAM0_ currently picked"),
_("Objects"),
"res/conditions/nbObjet24.png")
.AddParameter("objectListOrEmptyWithoutPicking", _("Object"))
.UseStandardParameters("number")
.MarkAsSimple();
.MarkAsSimple();
extension
.AddCondition(
@@ -1552,8 +1526,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"currently picked in the event"),
"",
"res/conditions/nbObjet.png")
.AddParameter("objectList", _("Object"))
.SetHidden(); // Deprecated
.AddParameter("objectList", _("Object"));
obj.AddStrExpression("ObjectName",
_("Object name"),

View File

@@ -229,15 +229,6 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
"res/mathfunction.png")
.AddParameter("expression", _("Expression"));
extension
.AddExpression("ceilTo",
_("Ceil (round up) to a decimal point"),
_("Round number up to the Nth decimal place"),
"",
"res/mathfunction.png")
.AddParameter("expression", _("Expression"))
.AddParameter("expression", _("Expression"), "", true);
extension
.AddExpression("floor",
_("Floor (round down)"),
@@ -246,15 +237,6 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
"res/mathfunction.png")
.AddParameter("expression", _("Expression"));
extension
.AddExpression("floorTo",
_("Floor (round down) to a decimal point"),
_("Round number down to the Nth decimal place"),
"",
"res/mathfunction.png")
.AddParameter("expression", _("Expression"))
.AddParameter("expression", _("Expression"), "", true);
extension
.AddExpression("cos",
_("Cosine"),
@@ -313,15 +295,6 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
"res/mathfunction.png")
.AddParameter("expression", _("Expression"));
extension
.AddExpression("roundTo",
_("Round to a decimal point"),
_("Round a number to the Nth decimal place"),
"",
"res/mathfunction.png")
.AddParameter("expression", _("Expression"))
.AddParameter("expression", _("Expression"), "", true);
extension
.AddExpression("exp",
_("Exponential"),

View File

@@ -311,8 +311,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
_("Multitouch"),
"res/conditions/touch24.png",
"res/conditions/touch.png")
.AddCodeOnlyParameter("currentScene", "")
.SetHidden();
.AddCodeOnlyParameter("currentScene", "");
extension
.AddCondition(
@@ -327,54 +326,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
_("Multitouch"),
"res/conditions/touch24.png",
"res/conditions/touch.png")
.AddCodeOnlyParameter("currentScene", "")
.SetHidden();
extension
.AddCondition(
"HasAnyTouchStarted",
_("A new touch has started"),
_("Check if a touch has just started on this frame. The touch identifiers can be "
"accessed using StartedTouchId() and StartedTouchCount()."),
_("A new touch has started"),
_("Multitouch"),
"res/conditions/touch24.png",
"res/conditions/touch.png")
.AddCodeOnlyParameter("currentScene", "");
extension
.AddExpression(
"StartedTouchCount",
_("Started touch count"),
_("The number of touches that have just started on this frame. The touch identifiers can be "
"accessed using StartedTouchId()."),
_("Multitouch"),
"res/conditions/touch.png")
.AddCodeOnlyParameter("currentScene", "");
extension
.AddExpression(
"StartedTouchId",
_("Started touch identifier"),
_("The identifier of the touch that has just started on this frame. The touch number of touches can be "
"accessed using StartedTouchCount()."),
_("Multitouch"),
"res/conditions/touch.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Touch index"));
extension
.AddCondition(
"HasTouchEnded",
_("A touch has ended"),
_("Check if a touch has ended."),
_("The touch with identifier _PARAM1_ has ended"),
_("Multitouch"),
"res/conditions/touch24.png",
"res/conditions/touch.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Touch identifier"));
extension
.AddExpression("MouseWheelDelta",
_("Mouse wheel: Displacement"),
@@ -389,8 +342,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
_("Identifier of the last touch"),
_("Multitouch"),
"res/conditions/touch.png")
.AddCodeOnlyParameter("currentScene", "")
.SetHidden();
.AddCodeOnlyParameter("currentScene", "");
extension
.AddExpression("LastEndedTouchId",
@@ -398,8 +350,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
_("Identifier of the last ended touch"),
_("Multitouch"),
"res/conditions/touch.png")
.AddCodeOnlyParameter("currentScene", "")
.SetHidden();
.AddCodeOnlyParameter("currentScene", "");
}
} // namespace gd

View File

@@ -121,7 +121,7 @@ void Direction::UnserializeFrom(const gd::SerializerElement& element) {
polygonElement.GetChild(k);
polygon.vertices.push_back(
gd::Vector2f(verticeElement.GetDoubleAttribute("x"),
sf::Vector2f(verticeElement.GetDoubleAttribute("x"),
verticeElement.GetDoubleAttribute("y")));
}

View File

@@ -4,7 +4,7 @@
* reserved. This project is released under the MIT License.
*/
#include "Polygon2d.h"
#include "GDCore/Vector2.h"
#include <SFML/System/Vector2.hpp>
#include <cmath>
#include <iostream>
@@ -28,7 +28,7 @@ void Polygon2d::Move(float x, float y) {
}
void Polygon2d::ComputeEdges() const {
gd::Vector2f v1, v2;
sf::Vector2f v1, v2;
edges.clear();
for (std::size_t i = 0; i < vertices.size(); i++) {
@@ -62,8 +62,8 @@ bool Polygon2d::IsConvex() const {
return true;
}
gd::Vector2f Polygon2d::ComputeCenter() const {
gd::Vector2f center;
sf::Vector2f Polygon2d::ComputeCenter() const {
sf::Vector2f center;
for (std::size_t i = 0; i < vertices.size(); i++) {
center.x += vertices[i].x;
@@ -77,10 +77,10 @@ gd::Vector2f Polygon2d::ComputeCenter() const {
Polygon2d Polygon2d::CreateRectangle(float width, float height) {
Polygon2d rect;
rect.vertices.push_back(gd::Vector2f(-width / 2.0f, -height / 2.0f));
rect.vertices.push_back(gd::Vector2f(+width / 2.0f, -height / 2.0f));
rect.vertices.push_back(gd::Vector2f(+width / 2.0f, +height / 2.0f));
rect.vertices.push_back(gd::Vector2f(-width / 2.0f, +height / 2.0f));
rect.vertices.push_back(sf::Vector2f(-width / 2.0f, -height / 2.0f));
rect.vertices.push_back(sf::Vector2f(+width / 2.0f, -height / 2.0f));
rect.vertices.push_back(sf::Vector2f(+width / 2.0f, +height / 2.0f));
rect.vertices.push_back(sf::Vector2f(-width / 2.0f, +height / 2.0f));
return rect;
}

View File

@@ -5,7 +5,7 @@
*/
#ifndef GDCORE_POLYGON_H
#define GDCORE_POLYGON_H
#include "GDCore/Vector2.h"
#include <SFML/System/Vector2.hpp>
#include <vector>
/**
@@ -22,19 +22,19 @@ class GD_CORE_API Polygon2d {
Polygon2d(){};
virtual ~Polygon2d(){};
std::vector<gd::Vector2f> vertices; ///< The vertices composing the polygon
mutable std::vector<gd::Vector2f>
std::vector<sf::Vector2f> vertices; ///< The vertices composing the polygon
mutable std::vector<sf::Vector2f>
edges; ///< Edges. Can be computed from vertices using ComputeEdges()
/**
* \brief Get the vertices composing the polygon.
*/
std::vector<gd::Vector2f>& GetVertices() { return vertices; }
std::vector<sf::Vector2f>& GetVertices() { return vertices; }
/**
* \brief Get the vertices composing the polygon.
*/
const std::vector<gd::Vector2f>& GetVertices() const { return vertices; }
const std::vector<sf::Vector2f>& GetVertices() const { return vertices; }
/**
* \brief Moves each vertices from the given amount.
@@ -68,7 +68,7 @@ class GD_CORE_API Polygon2d {
/**
* \brief Return the position of the center of the polygon
*/
gd::Vector2f ComputeCenter() const;
sf::Vector2f ComputeCenter() const;
/** \name Tools
* Tool functions

View File

@@ -4,6 +4,7 @@
* reserved. This project is released under the MIT License.
*/
#include "GDCore/Extensions/Builtin/SpriteExtension/Sprite.h"
#include <SFML/Graphics/Sprite.hpp>
#include <iostream>
#include "GDCore/Extensions/Builtin/SpriteExtension/Polygon2d.h"

View File

@@ -6,6 +6,7 @@
#ifndef SPRITE_H
#define SPRITE_H
#include <SFML/Graphics/Sprite.hpp>
#include <memory>
#include "GDCore/Extensions/Builtin/SpriteExtension/Point.h"
#include "GDCore/Extensions/Builtin/SpriteExtension/Polygon2d.h"

View File

@@ -6,6 +6,7 @@
#include "GDCore/Extensions/Builtin/SpriteExtension/SpriteObject.h"
#include <SFML/Graphics.hpp>
#include <algorithm>
#include "GDCore/CommonTools.h"

View File

@@ -20,7 +20,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsTimeExtension(
"for slow motion effects).",
"Florian Rival",
"Open source (MIT License)")
.SetExtensionHelpPath("/all-features/timers-and-time");
.SetExtensionHelpPath("/all-features/timers");
extension.AddInstructionOrExpressionGroupMetadata(
_("Timers and time")
)
@@ -141,6 +141,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsTimeExtension(
_("Change time scale"),
_("Change the time scale of the scene."),
_("Set the time scale of the scene to _PARAM1_"),
"",
"res/actions/time24.png",
"res/actions/time.png")
@@ -148,19 +149,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsTimeExtension(
.AddParameter("expression",
_("Scale (1: Default, 2: 2x faster, 0.5: 2x slower...)"));
extension
.AddAction("Wait",
_("Wait X seconds (experimental)"),
_("Waits a number of seconds before running "
"the next actions (and sub-events)."),
_("Wait _PARAM0_ seconds"),
"",
"res/timer.svg",
"res/timer.svg")
.AddParameter("expression", "Time to wait in seconds")
.SetHelpPath("/all-features/timers-and-time/wait-action")
.SetAsync();
extension
.AddExpression("TimeDelta",
_("Time elapsed since the last frame"),

View File

@@ -8,7 +8,6 @@
#include <functional>
#include <map>
#include <memory>
#include <algorithm>
#include "GDCore/Project/PropertyDescriptor.h"
#include "GDCore/String.h"

View File

@@ -22,7 +22,6 @@ InstructionMetadata::InstructionMetadata()
canHaveSubInstructions(false),
hidden(true),
usageComplexity(5),
isAsync(false),
isPrivate(false),
isObjectInstruction(false),
isBehaviorInstruction(false) {}
@@ -46,7 +45,6 @@ InstructionMetadata::InstructionMetadata(const gd::String& extensionNamespace_,
extensionNamespace(extensionNamespace_),
hidden(false),
usageComplexity(5),
isAsync(false),
isPrivate(false),
isObjectInstruction(false),
isBehaviorInstruction(false) {}

View File

@@ -9,7 +9,6 @@
#include <functional>
#include <map>
#include <memory>
#include <algorithm>
#include "GDCore/Events/Instruction.h"
#include "GDCore/String.h"
@@ -99,23 +98,6 @@ class GD_CORE_API InstructionMetadata {
return *this;
}
/**
* Check if the instruction is asynchronous - it will be running in the
* background, executing the instructions following it before the frame after
* it resolved.
*/
bool IsAsync() const { return isAsync; }
/**
* Set that the instruction is asynchronous - it will be running in the
* background, executing the instructions following it before the frame after
* it resolved.
*/
InstructionMetadata &SetAsync() {
isAsync = true;
return *this;
}
/**
* Notify that the instruction can have sub instructions.
*/
@@ -479,7 +461,6 @@ class GD_CORE_API InstructionMetadata {
int usageComplexity; ///< Evaluate the instruction from 0 (simple&easy to
///< use) to 10 (complex to understand)
bool isPrivate;
bool isAsync;
bool isObjectInstruction;
bool isBehaviorInstruction;
gd::String requiredBaseObjectCapability;

View File

@@ -9,7 +9,6 @@
#if defined(GD_IDE_ONLY)
#include <map>
#include <memory>
#include "GDCore/String.h"
namespace gd {
class Project;
@@ -152,16 +151,15 @@ class GD_CORE_API ParameterMetadata {
}
/**
* \brief Return true if the type of the parameter is representing one object
* (or more, i.e: an object group).
* \brief Return true if the type of the parameter is "object", "objectPtr" or
* "objectList".
*
* \see gd::ParameterMetadata::GetType
*/
static bool IsObject(const gd::String &parameterType) {
return parameterType == "object" || parameterType == "objectPtr" ||
parameterType == "objectList" ||
parameterType == "objectListOrEmptyIfJustDeclared" ||
parameterType == "objectListOrEmptyWithoutPicking";
parameterType == "objectListWithoutPicking";
}
/**
@@ -198,8 +196,7 @@ class GD_CORE_API ParameterMetadata {
parameterType == "objectPointName" ||
parameterType == "objectAnimationName" ||
parameterType == "functionParameterName" ||
parameterType == "externalLayoutName" ||
parameterType == "leaderboardId";
parameterType == "externalLayoutName";
} else if (type == "variable") {
return parameterType == "objectvar" || parameterType == "globalvar" ||
parameterType == "scenevar";

View File

@@ -117,16 +117,6 @@ void EffectsContainer::SwapEffects(std::size_t firstEffectIndex,
effects[secondEffectIndex] = temp;
}
void EffectsContainer::MoveEffect(std::size_t oldIndex, std::size_t newIndex) {
if (oldIndex >= effects.size() || newIndex >= effects.size() ||
newIndex == oldIndex)
return;
auto effect = effects[oldIndex];
effects.erase(effects.begin() + oldIndex);
effects.insert(effects.begin() + newIndex, effect);
}
void EffectsContainer::SerializeTo(SerializerElement& element) const {
element.ConsiderAsArrayOf("effect");
for (std::size_t i = 0; i < GetEffectsCount(); ++i) {

View File

@@ -7,7 +7,6 @@
#define GDCORE_EFFECTS_CONTAINER_H
#include <memory>
#include <vector>
#include <algorithm>
#include "GDCore/String.h"
@@ -90,11 +89,6 @@ class GD_CORE_API EffectsContainer {
*/
void RemoveEffect(const gd::String& name);
/**
* \brief Move the specified effect at a new position in the list.
*/
void MoveEffect(std::size_t oldIndex, std::size_t newIndex);
/**
* Swap the position of two effects.
*/

View File

@@ -5,7 +5,7 @@
*/
#ifndef GDCORE_OBJECT_H
#define GDCORE_OBJECT_H
#include "GDCore/Vector2.h"
#include <SFML/System/Vector2.hpp>
#include <map>
#include <memory>
#include <vector>

View File

@@ -7,7 +7,6 @@
#ifndef GDCORE_OBJECTGROUPSCONTAINER_H
#define GDCORE_OBJECTGROUPSCONTAINER_H
#include <vector>
#include <algorithm>
#include "GDCore/Project/ObjectGroup.h"
#include "GDCore/String.h"
namespace gd {
@@ -78,6 +77,7 @@ class GD_CORE_API ObjectGroupsContainer {
*/
bool IsEmpty() const { return objectGroups.empty(); };
#if defined(GD_IDE_ONLY)
/**
* \brief return the position of the group called "name" in the group list
*/
@@ -107,6 +107,7 @@ class GD_CORE_API ObjectGroupsContainer {
* \brief Move the specified group at a new position in the list.
*/
void Move(std::size_t oldIndex, std::size_t newIndex);
#endif
/**
* \brief Clear all groups of the container.

View File

@@ -9,6 +9,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <SFML/System/Utf.hpp>
#include <cctype>
#include <fstream>
#include <map>

View File

@@ -92,7 +92,7 @@ double Variable::GetValue() const {
return value;
} else if (type == Type::String) {
double retVal = str.empty() ? 0.0 : str.To<double>();
if (std::isnan(retVal)) retVal = 0.0;
if(std::isnan(retVal)) retVal = 0.0;
return retVal;
} else if (type == Type::Boolean) {
return boolVal ? 1.0 : 0.0;
@@ -188,15 +188,6 @@ const Variable& Variable::GetAtIndex(const size_t index) const {
return *childrenArray.at(index);
};
void Variable::MoveChildInArray(const size_t oldIndex, const size_t newIndex) {
if (oldIndex >= childrenArray.size() || newIndex >= childrenArray.size())
return;
std::shared_ptr<gd::Variable> object = std::move(childrenArray[oldIndex]);
childrenArray.erase(childrenArray.begin() + oldIndex);
childrenArray.insert(childrenArray.begin() + newIndex, std::move(object));
}
Variable& Variable::PushNew() { return GetAtIndex(GetChildrenCount()); };
void Variable::RemoveAtIndex(const size_t index) {
@@ -204,29 +195,8 @@ void Variable::RemoveAtIndex(const size_t index) {
childrenArray.erase(childrenArray.begin() + index);
};
bool Variable::InsertAtIndex(const gd::Variable& variable, const size_t index) {
if (type != Type::Array) return false;
auto newVariable = std::make_shared<gd::Variable>(variable);
if (index < childrenArray.size()) {
childrenArray.insert(childrenArray.begin() + index, newVariable);
} else {
childrenArray.push_back(newVariable);
}
return true;
};
bool Variable::InsertChild(const gd::String& name,
const gd::Variable& variable) {
if (type != Type::Structure || HasChild(name)) {
return false;
}
children[name] = std::make_shared<gd::Variable>(variable);
return true;
};
void Variable::SerializeTo(SerializerElement& element) const {
element.SetStringAttribute("type", TypeAsString(GetType()));
if (IsFolded()) element.SetBoolAttribute("folded", true);
if (type == Type::String) {
element.SetStringAttribute("value", GetString());
@@ -264,7 +234,6 @@ void Variable::UnserializeFrom(const SerializerElement& element) {
if (element.HasChild("children", "Children") && IsPrimitive(type))
type = Type::Structure;
// end of compatibility code
SetFolded(element.GetBoolAttribute("folded", false));
if (IsPrimitive(type)) {
if (type == Type::String) {
@@ -336,7 +305,6 @@ void Variable::RemoveRecursively(const gd::Variable& variableToRemove) {
Variable::Variable(const Variable& other)
: value(other.value),
str(other.str),
folded(other.folded),
boolVal(other.boolVal),
type(other.type) {
CopyChildren(other);
@@ -346,7 +314,6 @@ Variable& Variable::operator=(const Variable& other) {
if (this != &other) {
value = other.value;
str = other.str;
folded = other.folded;
boolVal = other.boolVal;
type = other.type;
CopyChildren(other);

View File

@@ -6,10 +6,10 @@
#ifndef GDCORE_VARIABLE_H
#define GDCORE_VARIABLE_H
#include <cmath>
#include <map>
#include <memory>
#include <vector>
#include <cmath>
#include "GDCore/String.h"
namespace gd {
@@ -98,7 +98,7 @@ class GD_CORE_API Variable {
void SetValue(double val) {
value = val;
// NaN values are not supported by GDevelop nor the serializer.
if (std::isnan(value)) value = 0.0;
if(std::isnan(value)) value = 0.0;
type = Type::Number;
}
@@ -185,9 +185,9 @@ class GD_CORE_API Variable {
* \brief Get the count of children that the variable has.
*/
size_t GetChildrenCount() const {
return type == Type::Structure ? children.size()
: type == Type::Array ? childrenArray.size()
: 0;
return type == Type::Structure
? children.size()
: type == Type::Array ? childrenArray.size() : 0;
};
/** \name Structure
@@ -290,38 +290,12 @@ class GD_CORE_API Variable {
*/
void RemoveAtIndex(const size_t index);
/**
* \brief Move child in array.
*/
void MoveChildInArray(const size_t oldIndex, const size_t newIndex);
/**
* \brief Insert child in array.
*/
bool InsertAtIndex(const gd::Variable& variable, const size_t index);
/**
* \brief Insert a child in a structure.
*/
bool InsertChild(const gd::String& name, const gd::Variable& variable);
/**
* \brief Get the vector containing all the children.
*/
const std::vector<std::shared_ptr<Variable>>& GetAllChildrenArray() const {
return childrenArray;
}
/**
* \brief Set if the children must be folded.
*/
void SetFolded(bool fold = true) { folded = fold; }
/**
* \brief True if the children should be folded in the variables editor.
*/
bool IsFolded() const { return folded; }
///@}
///@}
@@ -351,7 +325,6 @@ class GD_CORE_API Variable {
*/
static Type StringAsType(const gd::String& str);
bool folded;
mutable Type type;
mutable gd::String str;
mutable double value;

View File

@@ -4,10 +4,8 @@
* reserved. This project is released under the MIT License.
*/
#include "GDCore/Project/VariablesContainer.h"
#include <algorithm>
#include <iostream>
#include "GDCore/Project/Variable.h"
#include "GDCore/Serialization/SerializerElement.h"
#include "GDCore/String.h"
@@ -90,6 +88,7 @@ Variable& VariablesContainer::Insert(const gd::String& name,
}
}
#if defined(GD_IDE_ONLY)
void VariablesContainer::Remove(const gd::String& varName) {
variables.erase(
std::remove_if(
@@ -152,14 +151,13 @@ void VariablesContainer::Swap(std::size_t firstVariableIndex,
}
void VariablesContainer::Move(std::size_t oldIndex, std::size_t newIndex) {
if (oldIndex >= variables.size() || newIndex >= variables.size() ||
oldIndex == newIndex)
return;
if (oldIndex >= variables.size() || newIndex >= variables.size()) return;
auto nameAndVariable = variables[oldIndex];
variables.erase(variables.begin() + oldIndex);
variables.insert(variables.begin() + newIndex, nameAndVariable);
}
#endif
void VariablesContainer::SerializeTo(SerializerElement& element) const {
element.ConsiderAsArrayOf("variable");

View File

@@ -77,6 +77,8 @@ bool SerializerElement::GetBoolAttribute(const gd::String& name,
}
}
std::cout << "Bool attribute \"" << name << "\" not found, returning "
<< defaultValue;
return defaultValue;
}

View File

@@ -9,6 +9,7 @@
#include <algorithm>
#include <string.h>
#include <SFML/System/String.hpp>
#include "GDCore/CommonTools.h"
#include "GDCore/Utf8/utf8proc.h"
@@ -27,6 +28,11 @@ String::String(const char *characters) : m_string()
*this = characters;
}
String::String(const sf::String &string) : m_string()
{
*this = string;
}
String::String(const std::u32string &string) : m_string()
{
*this = string;
@@ -38,6 +44,26 @@ String& String::operator=(const char *characters)
return *this;
}
String& String::operator=(const sf::String &string)
{
m_string.clear();
//In theory, an UTF8 character can be up to 6 bytes (even if in the current Unicode standard,
//the last character is 4 bytes long when encoded in UTF8).
//So, reserve the maximum possible size to avoid reallocations.
m_string.reserve( string.getSize() * 6 );
//Push_back all characters inside the string.
for( sf::String::ConstIterator it = string.begin(); it != string.end(); ++it )
{
push_back( *it );
}
m_string.shrink_to_fit();
return *this;
}
String& String::operator=(const std::u32string &string)
{
m_string.clear();
@@ -86,7 +112,7 @@ String::const_iterator String::end() const
String String::FromLocale( const std::string &localizedString )
{
#if defined(WINDOWS)
return FromUTF8(localizedString); //Don't need to use the current locale, on Windows, std::locale is always the C locale
return FromSfString(sf::String(localizedString)); //Don't need to use the current locale, on Windows, std::locale is always the C locale
#elif defined(MACOS)
return FromUTF8(localizedString); //Assume UTF8 is the current locale
#elif defined(EMSCRIPTEN)
@@ -98,7 +124,7 @@ String String::FromLocale( const std::string &localizedString )
std::locale("").name().find("UTF8") != std::string::npos)
return FromUTF8(localizedString); //UTF8 is already the current locale
else
return FromUTF8(localizedString); //Use the current locale (std::locale("")) for conversion
return FromSfString(sf::String(localizedString, std::locale(""))); //Use the current locale (std::locale("")) for conversion
#endif
}
@@ -110,6 +136,11 @@ String String::FromUTF32( const std::u32string &string )
return str;
}
String String::FromSfString( const sf::String &sfString )
{
return String(sfString);
}
String String::FromUTF8( const std::string &utf8Str )
{
String str(utf8Str.c_str());
@@ -133,7 +164,7 @@ String String::FromWide( const std::wstring &wstr )
std::string String::ToLocale() const
{
#if defined(WINDOWS)
return m_string;
return ToSfString().toAnsiString();
#elif defined(MACOS)
return m_string;
#elif defined(EMSCRIPTEN)
@@ -145,7 +176,7 @@ std::string String::ToLocale() const
std::locale("").name().find("UTF8") != std::string::npos)
return m_string; //UTF8 is already the current locale on Linux
else
return m_string; //Use the current locale for conversion
return ToSfString().toAnsiString(std::locale("")); //Use the current locale for conversion
#endif
}
@@ -160,6 +191,20 @@ std::u32string String::ToUTF32() const
return u32str;
}
sf::String String::ToSfString() const
{
sf::String str;
for(const_iterator it = begin(); it != end(); ++it)
str += sf::String(static_cast<sf::Uint32>(*it));
return str;
}
String::operator sf::String() const
{
return ToSfString();
}
std::string String::ToUTF8() const
{
return m_string;

View File

@@ -13,9 +13,12 @@
#include <sstream>
#include <string>
#include <vector>
#include <SFML/System/String.hpp>
#include "GDCore/Utf8/utf8.h"
namespace sf {class String;};
namespace gd
{
@@ -118,6 +121,11 @@ public:
*/
String(const std::u32string &string);
/**
* Constructs a string from an sf::String.
*/
String(const sf::String &string);
/**
* \}
*/
@@ -138,6 +146,8 @@ public:
*/
String& operator=(const char *characters);
String& operator=(const sf::String &string);
String& operator=(const std::u32string &string);
/**
@@ -219,6 +229,7 @@ public:
static String From(T value)
{
static_assert(!std::is_same<T, std::string>::value, "Can't use gd::String::From with std::string.");
static_assert(!std::is_same<T, sf::String>::value, "Can't use gd::String::From with sf::String.");
std::ostringstream oss;
oss << value;
@@ -233,6 +244,7 @@ public:
T To() const
{
static_assert(!std::is_same<T, std::string>::value, "Can't use gd::String::To with std::string.");
static_assert(!std::is_same<T, sf::String>::value, "Can't use gd::String::To with sf::String.");
T value;
std::istringstream oss(m_string);
@@ -262,6 +274,13 @@ public:
*/
static String FromUTF32( const std::u32string &string );
/**
* \return a String created from a sf::String (UTF32).
*
* See \ref Conversions1 for more information.
*/
static String FromSfString( const sf::String &sfString );
/**
* \return a String created an UTF8 encoded std::string.
*/
@@ -293,6 +312,20 @@ public:
*/
std::u32string ToUTF32() const;
/**
* \return a sf::String from the current string.
*
* See \ref Conversions1 for more information.
*/
sf::String ToSfString() const;
/**
* Implicit conversion operator to sf::String.
*
* See \ref Conversions1 for more information.
*/
operator sf::String() const;
/**
* \return a UTF8 encoded std::string from the current string.
*/
@@ -852,7 +885,7 @@ namespace std
* on the string size and so is the operator[]().
*
* \section Conversion Conversions from/to other string types
* The String handles implicit conversion with std::String (implicit constructor and implicit conversion
* The String handles implicit conversion with sf::String (implicit constructor and implicit conversion
* operator).
*
* **However, this is not the case with std::string** as this conversion is not often lossless (mostly on Windows).
@@ -861,6 +894,16 @@ namespace std
* directly use the operator=() or the constructor as they are supporting const char* as argument (it assumes the string
* literal is encoded in UTF8, so you'll need to put the u8 prefix).
*
* \subsection Conversions1 Implicit conversion from/to sf::String
* \code
* //Get a String from sf::String
* sf::String sfmlStr("This is a test ! ");
* gd::String str1(sfmlStr); //Now contains "This is a test ! " encoded in UTF8
*
* //Get a sf::String from String
* sf::String anotherSfmlString = str; //anotherSfmlString now contains "Another test ! "
* \endcode
*
* \subsection Conversions2 Conversion from/to std::string
* \code
* //Get a String from a std::string encoded in the current locale

View File

@@ -0,0 +1,200 @@
#include "GDCore/Tools/FileStream.h"
#if defined(WINDOWS)
#if __GLIBCXX__
#include <ext/stdio_filebuf.h>
#endif
#endif
namespace gd {
namespace {
#if FSTREAM_WINDOWS_MINGW
#define MODE(in_val, out_val, trunc_val, app_val) \
((((mode & std::ios_base::in) != 0) == in_val) && \
(((mode & std::ios_base::out) != 0) == out_val) && \
(((mode & std::ios_base::trunc) != 0) == trunc_val) && \
(((mode & std::ios_base::app) != 0) == app_val))
std::wstring GetStdioMode(std::ios_base::openmode mode) {
std::wstring strMode;
/// Thanks to https://gcc.gnu.org/ml/libstdc++/2007-06/msg00013.html
if (MODE(false, true, false, false))
strMode += L"w";
else if (MODE(false, true, false, true))
strMode += L"a";
else if (MODE(true, true, false, true))
strMode += L"a+";
else if (MODE(false, true, true, false))
strMode += L"w";
else if (MODE(true, false, false, false))
strMode += L"r";
else if (MODE(true, true, false, false))
strMode += L"r+";
else if (MODE(true, true, true, false))
strMode += L"w+";
if ((mode & std::ios_base::binary) != 0) strMode += L"b";
return strMode;
}
#endif
/**
* Open the given file into a filebuf and return it.
* On Windows, return the associated FILE* inside the file argument.
*/
FileStream::InternalBufferType* OpenBuffer(const gd::String& path,
std::ios_base::openmode mode,
FILE** file) {
#if FSTREAM_WINDOWS_MINGW
*file = _wfopen(path.ToWide().c_str(), GetStdioMode(mode).c_str());
if (!(*file)) return nullptr;
return new __gnu_cxx::stdio_filebuf<char>(*file, mode);
#else
auto* filebuffer = new std::filebuf();
return filebuffer->open(path.ToLocale().c_str(), mode);
#endif
}
} // namespace
FileStream::FileStream() : std::iostream(nullptr) {}
FileStream::FileStream(const gd::String& path, std::ios_base::openmode mode)
: std::iostream(nullptr),
m_file(nullptr),
m_buffer(OpenBuffer(path, mode, &m_file)) {
setstate(ios_base::goodbit);
if (m_buffer) {
std::iostream::init(m_buffer.get());
if ((mode & std::ios_base::ate) != 0) seekg(0, end);
} else
setstate(ios_base::badbit);
}
FileStream::~FileStream() {
if (is_open()) close();
}
/*
WILL WORK with GCC>=5 (not 4.9 used on Windows)
FileStream::FileStream(FileStream && other) :
std::iostream(std::move(other)),
m_buffer(std::move(other.m_buffer))
{
}*/
/*FileStream& FileStream::operator=(FileStream && other)
{
std::iostream::operator=(std::move(other));
m_buffer = std::move(other.m_buffer);
}*/
void FileStream::open(const gd::String& path, std::ios_base::openmode mode) {
setstate(ios_base::goodbit);
if (is_open()) {
setstate(ios_base::failbit);
std::cout << "is_open true when trying to open!" << std::endl;
} else {
auto* newBuffer = OpenBuffer(path, mode, &m_file);
if (newBuffer) {
m_buffer.reset(newBuffer);
std::iostream::init(m_buffer.get());
if ((mode & std::ios_base::ate) != 0) seekg(0, end);
} else {
setstate(ios_base::badbit);
}
}
}
bool FileStream::is_open() const {
if (!m_buffer) return false;
return m_buffer->is_open();
}
void FileStream::close() {
#if FSTREAM_WINDOWS_MINGW
if (m_buffer) m_buffer->close();
if (m_file && fclose(m_file) != 0) {
setstate(ios_base::failbit);
}
m_buffer.reset(nullptr);
m_file = nullptr;
#else
if (!m_buffer || m_buffer->close() == nullptr) {
setstate(ios_base::failbit);
} else {
m_buffer.reset(nullptr);
}
#endif
}
/*void FileStream::swap(FileStream & other) //WILL WORK with GCC>=5 (not 4.9
used on Windows)
{
std::iostream::swap(other);
std::swap(m_buffer, other.m_buffer);
}*/
SFMLFileStream::SFMLFileStream() : m_file(nullptr) {}
SFMLFileStream::~SFMLFileStream() {
if (m_file) fclose(m_file);
}
bool SFMLFileStream::open(const gd::String& filename) {
if (m_file) fclose(m_file);
#if FSTREAM_WINDOWS_MINGW
m_file = _wfopen(filename.ToWide().c_str(), L"rb");
#else
m_file = fopen(filename.ToLocale().c_str(), "rb");
#endif
return m_file != NULL;
}
sf::Int64 SFMLFileStream::read(void* data, sf::Int64 size) {
if (m_file)
return fread(data, 1, static_cast<std::size_t>(size), m_file);
else
return -1;
}
sf::Int64 SFMLFileStream::seek(sf::Int64 position) {
if (m_file) {
fseek(m_file, static_cast<std::size_t>(position), SEEK_SET);
return tell();
} else {
return -1;
}
}
sf::Int64 SFMLFileStream::tell() {
if (m_file)
return ftell(m_file);
else
return -1;
}
sf::Int64 SFMLFileStream::getSize() {
if (m_file) {
sf::Int64 position = tell();
fseek(m_file, 0, SEEK_END);
sf::Int64 size = tell();
seek(position);
return size;
} else {
return -1;
}
}
} // namespace gd

View File

@@ -0,0 +1,82 @@
#ifndef GDCORE_FSTREAMTOOLS
#define GDCORE_FSTREAMTOOLS
#include <iostream>
#include <memory>
#include <SFML/System.hpp>
#include "GDCore/String.h"
#if defined(WINDOWS) && __GLIBCXX__
#include <ext/stdio_filebuf.h>
#else
#include <fstream> //for std::filebuf
#endif
namespace gd {
/**
* Similar to std::i/ofstream except that it can open file with
* gd::String paths (useful on Windows where fstream doesn't
* support wide paths).
*/
class GD_CORE_API FileStream : public std::iostream {
public:
#if defined(WINDOWS) && __GLIBCXX__
using InternalBufferType = std::basic_filebuf<char>;
#else
using InternalBufferType = std::filebuf;
#endif
FileStream();
FileStream(const gd::String& path, std::ios_base::openmode mode);
~FileStream();
FileStream(const FileStream& other) = delete;
FileStream(FileStream&& other) = delete; // HACK for GCC 4.9 (Windows)
// FileStream(FileStream && other); WILL WORK with GCC>=5 (not 4.9 used on
// Windows)
FileStream& operator=(const FileStream& other) = delete;
FileStream& operator=(FileStream&& other) =
delete; // HACK for GCC 4.9 (Windows)
// FileStream& operator=(FileStream && other); WILL WORK with GCC>=5 (not 4.9
// used on Windows)
void open(const gd::String& path, std::ios_base::openmode mode);
bool is_open() const;
void close();
// void swap(FileStream & other); //WILL WORK with GCC>=5 (not 4.9 used on
// Windows)
private:
FILE* m_file;
std::unique_ptr<InternalBufferType> m_buffer;
};
class GD_CORE_API SFMLFileStream : public sf::InputStream {
public:
SFMLFileStream();
~SFMLFileStream();
bool open(const gd::String& filename);
virtual sf::Int64 read(void* data, sf::Int64 size);
virtual sf::Int64 seek(sf::Int64 position);
virtual sf::Int64 tell();
virtual sf::Int64 getSize();
private:
FILE* m_file;
};
} // namespace gd
#endif

View File

@@ -0,0 +1,19 @@
#include <SFML/OpenGL.hpp>
#include <cmath>
namespace OpenGLTools {
void GD_CORE_API PerspectiveGL(GLdouble fovY,
GLdouble aspect,
GLdouble zNear,
GLdouble zFar) {
const GLdouble pi = 3.1415926535897932384626433832795;
GLdouble fW, fH;
fH = std::tan(fovY / 360 * pi) * zNear;
fW = fH * aspect;
glFrustum(-fW, fW, -fH, fH, zNear, zFar);
}
} // namespace OpenGLTools

View File

@@ -0,0 +1,9 @@
#include <SFML/OpenGL.hpp>
namespace OpenGLTools {
void GD_CORE_API PerspectiveGL(GLdouble fovY,
GLdouble aspect,
GLdouble zNear,
GLdouble zFar);
}

View File

@@ -1,360 +0,0 @@
// This is adapted from SFML (https://github.com/SFML/SFML).
#ifndef GDCORE_VECTOR2_H
#define GDCORE_VECTOR2_H
namespace gd
{
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2016 Laurent Gomila (laurent@sfml-dev.org)
//
// 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.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
/// \brief Utility template class for manipulating
/// 2-dimensional vectors
///
////////////////////////////////////////////////////////////
template <typename T>
class Vector2
{
public:
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// Creates a Vector2(0, 0).
///
////////////////////////////////////////////////////////////
inline Vector2() :
x(0),
y(0)
{
}
////////////////////////////////////////////////////////////
/// \brief Construct the vector from its coordinates
///
/// \param X X coordinate
/// \param Y Y coordinate
///
////////////////////////////////////////////////////////////
inline Vector2(T X, T Y) :
x(X),
y(Y)
{
}
////////////////////////////////////////////////////////////
/// \brief Construct the vector from another type of vector
///
/// This constructor doesn't replace the copy constructor,
/// it's called only when U != T.
/// A call to this constructor will fail to compile if U
/// is not convertible to T.
///
/// \param vector Vector to convert
///
////////////////////////////////////////////////////////////
template <typename U>
inline explicit Vector2(const Vector2<U>& vector) :
x(static_cast<T>(vector.x)),
y(static_cast<T>(vector.y))
{
}
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
T x; ///< X coordinate of the vector
T y; ///< Y coordinate of the vector
};
////////////////////////////////////////////////////////////
/// \relates Vector2
/// \brief Overload of unary operator -
///
/// \param right Vector to negate
///
/// \return Memberwise opposite of the vector
///
////////////////////////////////////////////////////////////
template <typename T>
inline Vector2<T> operator -(const Vector2<T>& right)
{
return Vector2<T>(-right.x, -right.y);
}
////////////////////////////////////////////////////////////
/// \relates Vector2
/// \brief Overload of binary operator +=
///
/// This operator performs a memberwise addition of both vectors,
/// and assigns the result to \a left.
///
/// \param left Left operand (a vector)
/// \param right Right operand (a vector)
///
/// \return Reference to \a left
///
////////////////////////////////////////////////////////////
template <typename T>
inline Vector2<T>& operator +=(Vector2<T>& left, const Vector2<T>& right)
{
left.x += right.x;
left.y += right.y;
return left;
}
////////////////////////////////////////////////////////////
/// \relates Vector2
/// \brief Overload of binary operator -=
///
/// This operator performs a memberwise subtraction of both vectors,
/// and assigns the result to \a left.
///
/// \param left Left operand (a vector)
/// \param right Right operand (a vector)
///
/// \return Reference to \a left
///
////////////////////////////////////////////////////////////
template <typename T>
inline Vector2<T>& operator -=(Vector2<T>& left, const Vector2<T>& right)
{
left.x -= right.x;
left.y -= right.y;
return left;
}
////////////////////////////////////////////////////////////
/// \relates Vector2
/// \brief Overload of binary operator +
///
/// \param left Left operand (a vector)
/// \param right Right operand (a vector)
///
/// \return Memberwise addition of both vectors
///
////////////////////////////////////////////////////////////
template <typename T>
inline Vector2<T> operator +(const Vector2<T>& left, const Vector2<T>& right)
{
return Vector2<T>(left.x + right.x, left.y + right.y);
}
////////////////////////////////////////////////////////////
/// \relates Vector2
/// \brief Overload of binary operator -
///
/// \param left Left operand (a vector)
/// \param right Right operand (a vector)
///
/// \return Memberwise subtraction of both vectors
///
////////////////////////////////////////////////////////////
template <typename T>
inline Vector2<T> operator -(const Vector2<T>& left, const Vector2<T>& right)
{
return Vector2<T>(left.x - right.x, left.y - right.y);
}
////////////////////////////////////////////////////////////
/// \relates Vector2
/// \brief Overload of binary operator *
///
/// \param left Left operand (a vector)
/// \param right Right operand (a scalar value)
///
/// \return Memberwise multiplication by \a right
///
////////////////////////////////////////////////////////////
template <typename T>
inline Vector2<T> operator *(const Vector2<T>& left, T right)
{
return Vector2<T>(left.x * right, left.y * right);
}
////////////////////////////////////////////////////////////
/// \relates Vector2
/// \brief Overload of binary operator *
///
/// \param left Left operand (a scalar value)
/// \param right Right operand (a vector)
///
/// \return Memberwise multiplication by \a left
///
////////////////////////////////////////////////////////////
template <typename T>
inline Vector2<T> operator *(T left, const Vector2<T>& right)
{
return Vector2<T>(right.x * left, right.y * left);
}
////////////////////////////////////////////////////////////
/// \relates Vector2
/// \brief Overload of binary operator *=
///
/// This operator performs a memberwise multiplication by \a right,
/// and assigns the result to \a left.
///
/// \param left Left operand (a vector)
/// \param right Right operand (a scalar value)
///
/// \return Reference to \a left
///
////////////////////////////////////////////////////////////
template <typename T>
inline Vector2<T>& operator *=(Vector2<T>& left, T right)
{
left.x *= right;
left.y *= right;
return left;
}
////////////////////////////////////////////////////////////
/// \relates Vector2
/// \brief Overload of binary operator /
///
/// \param left Left operand (a vector)
/// \param right Right operand (a scalar value)
///
/// \return Memberwise division by \a right
///
////////////////////////////////////////////////////////////
template <typename T>
inline Vector2<T> operator /(const Vector2<T>& left, T right)
{
return Vector2<T>(left.x / right, left.y / right);
}
////////////////////////////////////////////////////////////
/// \relates Vector2
/// \brief Overload of binary operator /=
///
/// This operator performs a memberwise division by \a right,
/// and assigns the result to \a left.
///
/// \param left Left operand (a vector)
/// \param right Right operand (a scalar value)
///
/// \return Reference to \a left
///
////////////////////////////////////////////////////////////
template <typename T>
inline Vector2<T>& operator /=(Vector2<T>& left, T right)
{
left.x /= right;
left.y /= right;
return left;
}
////////////////////////////////////////////////////////////
/// \relates Vector2
/// \brief Overload of binary operator ==
///
/// This operator compares strict equality between two vectors.
///
/// \param left Left operand (a vector)
/// \param right Right operand (a vector)
///
/// \return True if \a left is equal to \a right
///
////////////////////////////////////////////////////////////
template <typename T>
inline bool operator ==(const Vector2<T>& left, const Vector2<T>& right)
{
return (left.x == right.x) && (left.y == right.y);
}
////////////////////////////////////////////////////////////
/// \relates Vector2
/// \brief Overload of binary operator !=
///
/// This operator compares strict difference between two vectors.
///
/// \param left Left operand (a vector)
/// \param right Right operand (a vector)
///
/// \return True if \a left is not equal to \a right
///
////////////////////////////////////////////////////////////
template <typename T>
inline bool operator !=(const Vector2<T>& left, const Vector2<T>& right)
{
return (left.x != right.x) || (left.y != right.y);
}
// Define the most common types
typedef Vector2<int> Vector2i;
typedef Vector2<unsigned int> Vector2u;
typedef Vector2<float> Vector2f;
} // namespace gd
#endif // GDCORE_VECTOR2_H
////////////////////////////////////////////////////////////
/// \class gd::Vector2
/// \ingroup CommonProgrammingTools
///
/// gd::Vector2 is a simple class that defines a mathematical
/// vector with two coordinates (x and y). It can be used to
/// represent anything that has two dimensions: a size, a point,
/// a velocity, etc.
///
/// The template parameter T is the type of the coordinates. It
/// can be any type that supports arithmetic operations (+, -, /, *)
/// and comparisons (==, !=), for example int or float.
///
/// You generally don't have to care about the templated form (gd::Vector2<T>),
/// the most common specializations have special typedefs:
/// \li gd::Vector2<float> is gd::Vector2f
/// \li gd::Vector2<int> is gd::Vector2i
/// \li gd::Vector2<unsigned int> is gd::Vector2u
///
/// The gd::Vector2 class has a small and simple interface, its x and y members
/// can be accessed directly (there are no accessors like setX(), getX()) and it
/// contains no mathematical function like dot product, cross product, length, etc.
///
/// Usage example:
/// \code
/// gd::Vector2f v1(16.5f, 24.f);
/// v1.x = 18.2f;
/// float y = v1.y;
///
/// gd::Vector2f v2 = v1 * 5.f;
/// gd::Vector2f v3;
/// v3 = v1 + v2;
///
/// bool different = (v2 != v3);
/// \endcode
///
/// Note: for 3-dimensional vectors, see gd::Vector3.
///
////////////////////////////////////////////////////////////

View File

@@ -75,11 +75,7 @@ TEST_CASE("EventsList", "[common][events]") {
size_t endMemory = gd::SystemStats::GetUsedVirtualMemory();
INFO("Memory used: " << endMemory - startMemory << "KB");
#if defined(WINDOWS)
REQUIRE(3000 >= endMemory - startMemory);
#else
REQUIRE(1500 >= endMemory - startMemory);
#endif
REQUIRE(1500 >= endMemory - startMemory);
}
}

View File

@@ -31,7 +31,7 @@ TEST_CASE("EventsCodeGenerationContext", "[common][events]") {
gd::EventsCodeGenerationContext c1(&maxDepth);
c1.ObjectsListNeeded("c1.object1");
c1.ObjectsListNeeded("c1.object2");
c1.ObjectsListNeededOrEmptyIfJustDeclared("c1.noPicking1");
c1.ObjectsListWithoutPickingNeeded("c1.noPicking1");
gd::EventsCodeGenerationContext c2;
c2.InheritsFrom(c1);
@@ -47,7 +47,7 @@ TEST_CASE("EventsCodeGenerationContext", "[common][events]") {
gd::EventsCodeGenerationContext c5;
c5.InheritsFrom(c2);
c5.ObjectsListNeededOrEmptyIfJustDeclared("c5.noPicking1");
c5.ObjectsListWithoutPickingNeeded("c5.noPicking1");
c5.ObjectsListNeeded("c5.object1");
c5.ObjectsListNeeded("c1.object2");
c5.EmptyObjectsListNeeded("c5.empty1");
@@ -70,36 +70,36 @@ TEST_CASE("EventsCodeGenerationContext", "[common][events]") {
}
SECTION("Object list needed") {
REQUIRE(c1.GetObjectsListsAlreadyDeclaredByParents() == std::set<gd::String>());
REQUIRE(c1.GetObjectsListsAlreadyDeclared() == std::set<gd::String>());
REQUIRE(c1.GetObjectsListsToBeDeclared() ==
std::set<gd::String>({"c1.object1", "c1.object2"}));
REQUIRE(c1.GetObjectsListsToBeEmptyIfJustDeclared() ==
REQUIRE(c1.GetObjectsListsToBeDeclaredWithoutPicking() ==
std::set<gd::String>({"c1.noPicking1"}));
REQUIRE(c1.GetAllObjectsToBeDeclared() ==
std::set<gd::String>({"c1.object1", "c1.object2", "c1.noPicking1"}));
REQUIRE(c2.GetObjectsListsAlreadyDeclaredByParents() ==
REQUIRE(c2.GetObjectsListsAlreadyDeclared() ==
std::set<gd::String>({"c1.object1", "c1.object2", "c1.noPicking1"}));
REQUIRE(c2.GetObjectsListsToBeDeclared() ==
std::set<gd::String>({"c2.object1"}));
REQUIRE(c2.GetObjectsListsToBeEmptyIfJustDeclared() == std::set<gd::String>());
REQUIRE(c2.GetObjectsListsToBeDeclaredWithoutPicking() == std::set<gd::String>());
REQUIRE(c2.GetAllObjectsToBeDeclared() ==
std::set<gd::String>({"c2.object1"}));
REQUIRE(c3.GetObjectsListsAlreadyDeclaredByParents() ==
REQUIRE(c3.GetObjectsListsAlreadyDeclared() ==
std::set<gd::String>({"c1.object1", "c1.object2", "c1.noPicking1"}));
REQUIRE(c3.GetObjectsListsToBeDeclared() ==
std::set<gd::String>({"c3.object1", "c1.object2"}));
REQUIRE(c3.GetObjectsListsToBeEmptyIfJustDeclared() == std::set<gd::String>());
REQUIRE(c3.GetObjectsListsToBeDeclaredWithoutPicking() == std::set<gd::String>());
REQUIRE(c3.GetAllObjectsToBeDeclared() ==
std::set<gd::String>({"c3.object1", "c1.object2"}));
REQUIRE(c5.GetObjectsListsAlreadyDeclaredByParents() ==
REQUIRE(c5.GetObjectsListsAlreadyDeclared() ==
std::set<gd::String>(
{"c1.object1", "c1.object2", "c1.noPicking1", "c2.object1"}));
REQUIRE(c5.GetObjectsListsToBeDeclared() ==
std::set<gd::String>({"c5.object1", "c1.object2"}));
REQUIRE(c5.GetObjectsListsToBeEmptyIfJustDeclared() ==
REQUIRE(c5.GetObjectsListsToBeDeclaredWithoutPicking() ==
std::set<gd::String>({"c5.noPicking1"}));
REQUIRE(c5.GetObjectsListsToBeDeclaredEmpty() ==
std::set<gd::String>({"c5.empty1"}));
@@ -107,18 +107,22 @@ TEST_CASE("EventsCodeGenerationContext", "[common][events]") {
std::set<gd::String>({"c5.object1", "c5.noPicking1", "c1.object2", "c5.empty1"}));
}
SECTION("ObjectAlreadyDeclaredByParents") {
REQUIRE(c1.ObjectAlreadyDeclaredByParents("c1.object1") == false);
REQUIRE(c2.ObjectAlreadyDeclaredByParents("c1.object1") == true);
REQUIRE(c3.ObjectAlreadyDeclaredByParents("c1.object1") == true);
REQUIRE(c4.ObjectAlreadyDeclaredByParents("c1.object1") == true);
REQUIRE(c5.ObjectAlreadyDeclaredByParents("c1.object1") == true);
SECTION("ObjectAlreadyDeclared") {
REQUIRE(c1.ObjectAlreadyDeclared("c1.object1") == false);
REQUIRE(c2.ObjectAlreadyDeclared("c1.object1") == true);
REQUIRE(c3.ObjectAlreadyDeclared("c1.object1") == true);
REQUIRE(c4.ObjectAlreadyDeclared("c1.object1") == true);
REQUIRE(c5.ObjectAlreadyDeclared("c1.object1") == true);
REQUIRE(c1.ObjectAlreadyDeclaredByParents("c2.object1") == false);
REQUIRE(c2.ObjectAlreadyDeclaredByParents("c2.object1") == false);
REQUIRE(c3.ObjectAlreadyDeclaredByParents("c2.object1") == false);
REQUIRE(c4.ObjectAlreadyDeclaredByParents("c2.object1") == true);
REQUIRE(c5.ObjectAlreadyDeclaredByParents("c2.object1") == true);
REQUIRE(c2.ObjectAlreadyDeclared("c2.object1") == false);
REQUIRE(c1.ObjectAlreadyDeclared("c2.object1") == false);
REQUIRE(c3.ObjectAlreadyDeclared("c2.object1") == false);
REQUIRE(c4.ObjectAlreadyDeclared("c2.object1") == true);
REQUIRE(c5.ObjectAlreadyDeclared("c2.object1") == true);
REQUIRE(c3.ObjectAlreadyDeclared("some object") == false);
c3.SetObjectDeclared("some object");
REQUIRE(c3.ObjectAlreadyDeclared("some object") == true);
}
SECTION("Object list last depth") {
@@ -182,87 +186,4 @@ TEST_CASE("EventsCodeGenerationContext", "[common][events]") {
REQUIRE(c7.IsSameObjectsList("c6.object3", c6) == false);
REQUIRE(c7.IsSameObjectsList("c5.empty1", c5) == false);
}
SECTION("Async") {
gd::EventsCodeGenerationContext c1;
c1.ObjectsListNeeded("c1.object1");
c1.ObjectsListNeeded("c1.object2");
c1.ObjectsListNeededOrEmptyIfJustDeclared("c1.possiblyEmpty1");
c1.EmptyObjectsListNeeded("c1.empty1");
gd::EventsCodeGenerationContext c2;
c2.InheritsAsAsyncCallbackFrom(c1);
c2.ObjectsListNeeded("c2.object1");
c2.ObjectsListNeededOrEmptyIfJustDeclared("c2.possiblyEmpty1");
c2.EmptyObjectsListNeeded("c2.empty1");
c2.ObjectsListNeeded("c1.object1");
gd::EventsCodeGenerationContext c3;
c3.InheritsAsAsyncCallbackFrom(c2);
c3.ObjectsListNeeded("c3.object1");
c3.ObjectsListNeededOrEmptyIfJustDeclared("c3.possiblyEmpty1");
c3.EmptyObjectsListNeeded("c3.empty1");
c3.ObjectsListNeeded("c1.object1");
gd::EventsCodeGenerationContext c4;
c4.InheritsFrom(c3);
c4.ObjectsListNeeded("c4.object1");
c4.ObjectsListNeededOrEmptyIfJustDeclared("c4.possiblyEmpty1");
c4.EmptyObjectsListNeeded("c4.empty1");
c4.ObjectsListNeeded("c1.object1");
c4.ObjectsListNeeded("c1.object2");
gd::EventsCodeGenerationContext c5;
c5.InheritsFrom(c4);
c5.ObjectsListNeeded("c5.object1");
c5.ObjectsListNeededOrEmptyIfJustDeclared("c5.possiblyEmpty1");
c5.EmptyObjectsListNeeded("c5.empty1");
c5.ObjectsListNeeded("c1.object1");
c5.ObjectsListNeeded("c1.object2");
REQUIRE(c1.ShouldUseAsyncObjectsList("c1.object1") == false);
REQUIRE(c1.ShouldUseAsyncObjectsList("c1.possiblyEmpty1") == false);
REQUIRE(c1.ShouldUseAsyncObjectsList("c1.empty1") == false);
// Objects declared in async callback are used traditionally:
REQUIRE(c2.ShouldUseAsyncObjectsList("c2.object1") == false);
REQUIRE(c2.ShouldUseAsyncObjectsList("c2.possiblyEmpty1") == false);
REQUIRE(c2.ShouldUseAsyncObjectsList("c2.empty1") == false);
// Objects declared in c1 are gotten from the async list in c2 and c3
// because these contexts use them and are async.
REQUIRE(c2.ShouldUseAsyncObjectsList("c1.object1") == true);
REQUIRE(c3.ShouldUseAsyncObjectsList("c1.object1") == true);
REQUIRE(c4.ShouldUseAsyncObjectsList("c1.object1") == false);
REQUIRE(c5.ShouldUseAsyncObjectsList("c1.object1") == false);
// Objects declared in c1 are gotten from the async list in c4
// because c3 is async (but is not using them)
REQUIRE(c4.ShouldUseAsyncObjectsList("c1.object2") == true);
// Objects declared in c1 but gotten from the async list in c4
// is used traditionnally:
REQUIRE(c5.ShouldUseAsyncObjectsList("c1.object2") == false);
// Objects declared in or after c3 are used traditionally:
REQUIRE(c3.ShouldUseAsyncObjectsList("c3.object1") == false);
REQUIRE(c4.ShouldUseAsyncObjectsList("c3.object1") == false);
REQUIRE(c5.ShouldUseAsyncObjectsList("c3.object1") == false);
REQUIRE(c3.ShouldUseAsyncObjectsList("c3.possiblyEmpty1") == false);
REQUIRE(c4.ShouldUseAsyncObjectsList("c3.possiblyEmpty1") == false);
REQUIRE(c5.ShouldUseAsyncObjectsList("c3.possiblyEmpty1") == false);
REQUIRE(c3.ShouldUseAsyncObjectsList("c3.empty1") == false);
REQUIRE(c4.ShouldUseAsyncObjectsList("c3.empty1") == false);
REQUIRE(c5.ShouldUseAsyncObjectsList("c3.empty1") == false);
REQUIRE(c4.ShouldUseAsyncObjectsList("c4.object1") == false);
REQUIRE(c4.ShouldUseAsyncObjectsList("c4.possiblyEmpty1") == false);
REQUIRE(c4.ShouldUseAsyncObjectsList("c4.empty1") == false);
REQUIRE(c5.ShouldUseAsyncObjectsList("c4.object1") == false);
REQUIRE(c5.ShouldUseAsyncObjectsList("c4.possiblyEmpty1") == false);
REQUIRE(c5.ShouldUseAsyncObjectsList("c4.empty1") == false);
REQUIRE(c5.ShouldUseAsyncObjectsList("c5.object1") == false);
REQUIRE(c5.ShouldUseAsyncObjectsList("c5.possiblyEmpty1") == false);
REQUIRE(c5.ShouldUseAsyncObjectsList("c5.empty1") == false);
}
}

90
Core/tests/FileStream.cpp Normal file
View File

@@ -0,0 +1,90 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
/**
* @file Tests covering FileStream class of GDevelop Core.
*/
#include "GDCore/Tools/FileStream.h"
#include <fstream>
#include <memory>
#include "GDCore/CommonTools.h"
#include "catch.hpp"
TEST_CASE("FileStream", "[common][fstream]") {
// Creating the test file
std::ofstream testFile("FileStreamTest.test");
REQUIRE(testFile.is_open());
testFile << "this is the first line of the test file!\n";
testFile << "the last line!";
testFile.close();
SECTION("Input file") {
gd::FileStream f;
f.open("FileStreamTest.test", std::ios_base::in);
REQUIRE(f.is_open() == true);
REQUIRE(f.tellg() == 0);
std::string lineContent;
REQUIRE(f.eof() == false);
std::getline(f, lineContent);
REQUIRE(lineContent == "this is the first line of the test file!");
REQUIRE(f.eof() == false);
std::getline(f, lineContent);
REQUIRE(lineContent == "the last line!");
REQUIRE(f.eof() == true);
REQUIRE(f.fail() == false);
f.close();
REQUIRE(f.is_open() == false);
REQUIRE(f.fail() == false);
}
SECTION("Output/Input file with special characters in filepath") {
gd::FileStream output("\xEA\x88\xA1.txt", std::ios_base::out);
REQUIRE(output.is_open() == true);
output << "TEST";
output.close();
gd::FileStream input("\xEA\x88\xA1.txt", std::ios_base::in);
REQUIRE(input.is_open() == true);
std::string lineContent;
REQUIRE(input.eof() == false);
std::getline(input, lineContent);
REQUIRE(lineContent == "TEST");
REQUIRE(input.eof() == true);
input.close();
REQUIRE(input.is_open() == false);
REQUIRE(input.fail() == false);
}
SECTION("File opening failure") {
gd::FileStream f("\xE4\x84\xA2",
std::ios_base::in); // A file that doesn't exist
REQUIRE(f.is_open() == false);
REQUIRE(f.fail() ==
true); // As the opening failed, the "fail" flag should be set
f.close();
REQUIRE(f.bad() == true); // As no files are opened, this should set the
// "bad" flag of the stream
}
SECTION("std::ios_base::ate") { // As ate is "emulated", needs testing
gd::FileStream f;
f.open("FileStreamTest.test", std::ios_base::in | std::ios_base::ate);
REQUIRE(f.is_open() == true);
REQUIRE(f.tellg() > 0);
}
}

View File

@@ -7,6 +7,7 @@
* @file Tests covering utf8 features from GDevelop Core.
*/
#include <SFML/System/String.hpp>
#include <exception>
#include <iostream>
#include <string>
@@ -18,8 +19,10 @@ TEST_CASE("Utf8 String", "[common][utf8]") {
SECTION("ctor & conversions") {
gd::String str = u8"UTF8 a été testé !";
sf::String sfStr = str;
std::u32string u32str = str.ToUTF32();
REQUIRE(str == gd::String::FromSfString(sfStr));
REQUIRE(str == gd::String::FromUTF32(u32str));
}
@@ -39,10 +42,8 @@ TEST_CASE("Utf8 String", "[common][utf8]") {
REQUIRE(str.substr(5, 7) == u8"a été t");
REQUIRE(str.substr(5, gd::String::npos) == u8"a été testé !");
// Windows doesn't seems to like exceptions.
#if !defined(WINDOWS)
REQUIRE_THROWS_AS(str.substr(50, 5), std::out_of_range);
#endif
REQUIRE_THROWS_AS(str.substr(50, 5), std::out_of_range);
}
SECTION("insert") {
@@ -50,9 +51,7 @@ TEST_CASE("Utf8 String", "[common][utf8]") {
str.insert(25, u8"vraiment ");
REQUIRE(str == u8"Une fonctionnalité a été vraiment testée !");
#if !defined(WINDOWS)
REQUIRE_THROWS_AS(str.insert(150, u8"This gonna fail"), std::out_of_range);
#endif
REQUIRE_THROWS_AS(str.insert(150, u8"This gonna fail"), std::out_of_range);
}
SECTION("replace") {
@@ -63,10 +62,8 @@ TEST_CASE("Utf8 String", "[common][utf8]") {
REQUIRE(str.replace(11, gd::String::npos, u8"vraiment très testé !") ==
u8"UTF8 a été vraiment très testé !");
#if !defined(WINDOWS)
REQUIRE_THROWS_AS(str.replace(50, 5, u8"Cela va planter."),
std::out_of_range);
#endif
REQUIRE_THROWS_AS(str.replace(50, 5, u8"Cela va planter."),
std::out_of_range);
// Testing the iterator version of replace
gd::String str2 = u8"UTF8 a été testé !";
@@ -97,10 +94,8 @@ TEST_CASE("Utf8 String", "[common][utf8]") {
REQUIRE(str == "UTF8");
}
{
#if !defined(WINDOWS)
gd::String str = u8"UTF8 a été testé !";
REQUIRE_THROWS_AS(str.erase(100, 5), std::out_of_range);
#endif
gd::String str = u8"UTF8 a été testé !";
REQUIRE_THROWS_AS(str.erase(100, 5), std::out_of_range);
}
{
gd::String str = u8"UTF8 a été testé !";

View File

@@ -0,0 +1,54 @@
# Clone SFML from its official directory using Git. Only
# do it if not already cloned to avoid triggering a whole
# recompilation every time CMake is run.
find_package(Git)
if(GIT_FOUND)
if (NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/SFML/readme.txt")
message( "Cloning SFML in ExtLibs/SFML with Git..." )
execute_process(
COMMAND ${GIT_EXECUTABLE} clone "https://www.github.com/SFML/SFML.git" SFML
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/
OUTPUT_QUIET)
message( "Resetting SFML source code to version 2.4.1..." )
execute_process(
COMMAND ${GIT_EXECUTABLE} reset --hard 2.4.1
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/SFML
OUTPUT_QUIET)
message( "Applying the patches..." )
file(GLOB SFML_PATCHES
LIST_DIRECTORIES FALSE
${CMAKE_CURRENT_SOURCE_DIR}/SFML-patches/*.patch)
if(SFML_PATCHES)
list(SORT SFML_PATCHES)
foreach(SFML_PATCH ${SFML_PATCHES})
message( "Applying patch: ${SFML_PATCH}..." )
execute_process(
COMMAND ${GIT_EXECUTABLE} apply ${SFML_PATCH} --ignore-whitespace
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/SFML
OUTPUT_QUIET)
endforeach()
endif()
else()
message( "SFML already downloaded." )
endif()
else()
message( "Git not found, make sure you have SFML >= 2.4 in ExtLibs/SFML and you applied the needed patches (from ExtLibs/SFML-patches)!" )
endif()
#SFML:
IF(NOT EMSCRIPTEN) #Don't build SFML binaries when compiling with emscripten (but keep include files!)
add_subdirectory(SFML)
set(sfml_lib_dir ${CMAKE_BINARY_DIR}/ExtLibs/SFML/lib PARENT_SCOPE)
set(sfml_LIBRARIES sfml-audio sfml-graphics sfml-window sfml-network sfml-system)
IF(WIN32)
set(sfml_LIBRARIES "${sfml_LIBRARIES}" ws2_32 user32 opengl32 glu32 psapi)
ELSEIF(NOT APPLE)
set(sfml_LIBRARIES "${sfml_LIBRARIES}" GLU GL)
ENDIF()
set(sfml_LIBRARIES "${sfml_LIBRARIES}" PARENT_SCOPE)
ENDIF()
set(sfml_include_dir ${CMAKE_CURRENT_SOURCE_DIR}/SFML/include PARENT_SCOPE)

View File

@@ -0,0 +1,19 @@
diff --git a/extlibs/headers/stb_image/stb_image.h b/extlibs/headers/stb_image/stb_image.h
index c3945c2..5fe1050 100644
--- a/extlibs/headers/stb_image/stb_image.h
+++ b/extlibs/headers/stb_image/stb_image.h
@@ -671,14 +671,9 @@ static int stbi__sse2_available()
static int stbi__sse2_available()
{
-#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 408 // GCC 4.8 or later
- // GCC 4.8+ has a nice way to do this
- return __builtin_cpu_supports("sse2");
-#else
// portable way to do this, preferably without using GCC inline ASM?
// just bail for now.
return 0;
-#endif
}
#endif
#endif

View File

@@ -0,0 +1,29 @@
From f55ee73a73398bb77ce9c63ff1a13d8053cb1d18 Mon Sep 17 00:00:00 2001
From: Florian Rival <Florian.Rival@gmail.com>
Date: Tue, 3 Jan 2017 21:15:11 +0100
Subject: [PATCH] Fix crash with SFML embeded in wxWidgets on OS X
---
src/SFML/Window/OSX/SFViewController.mm | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/SFML/Window/OSX/SFViewController.mm b/src/SFML/Window/OSX/SFViewController.mm
index 7d736e3..280ec2b 100644
--- a/src/SFML/Window/OSX/SFViewController.mm
+++ b/src/SFML/Window/OSX/SFViewController.mm
@@ -82,8 +82,12 @@ -(id)initWithView:(NSView *)view
////////////////////////////////////////////////////////
-(void)dealloc
{
+ NSLog(@"SFViewController::dealloc called on %@", self);
[self closeWindow];
+
+ // See https://github.com/SFML/SFML/issues/824
+ [[NSNotificationCenter defaultCenter] removeObserver:m_oglView];
[m_view release];
[m_oglView release];
--
2.7.4 (Apple Git-66)

View File

@@ -0,0 +1,13 @@
diff --git a/include/SFML/Config.hpp b/include/SFML/Config.hpp
index 9c68d84..2522d88 100644
--- a/include/SFML/Config.hpp
+++ b/include/SFML/Config.hpp
@@ -76,7 +76,7 @@
// Android
#define SFML_SYSTEM_ANDROID
- #elif defined(__linux__)
+ #elif defined(__linux__) || defined(EMSCRIPTEN)
// Linux
#define SFML_SYSTEM_LINUX

View File

@@ -45,7 +45,6 @@ module.exports = {
)
.addParameter('yesorno', _('Focus the window?'), '', false)
.setDefaultValue('true')
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -62,7 +61,6 @@ module.exports = {
'res/actions/window24.png',
'res/actions/window.png'
)
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -81,7 +79,6 @@ module.exports = {
)
.addParameter('yesorno', _('Show window?'), '', false)
.setDefaultValue('true')
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -98,7 +95,6 @@ module.exports = {
'res/actions/window24.png',
'res/actions/window.png'
)
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -117,7 +113,6 @@ module.exports = {
)
.addParameter('yesorno', _('Maximize window?'), '', false)
.setDefaultValue('true')
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -134,7 +129,6 @@ module.exports = {
'res/actions/window24.png',
'res/actions/window.png'
)
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -153,7 +147,6 @@ module.exports = {
)
.addParameter('yesorno', _('Minimize window?'), '', false)
.setDefaultValue('true')
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -170,7 +163,6 @@ module.exports = {
'res/actions/window24.png',
'res/actions/window.png'
)
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -189,7 +181,6 @@ module.exports = {
)
.addParameter('yesorno', _('Enable window?'), '', false)
.setDefaultValue('true')
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -206,7 +197,6 @@ module.exports = {
'res/actions/window24.png',
'res/actions/window.png'
)
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -225,7 +215,6 @@ module.exports = {
)
.addParameter('yesorno', _('Allow resizing?'), '', false)
.setDefaultValue('true')
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -242,7 +231,6 @@ module.exports = {
'res/actions/window24.png',
'res/actions/window.png'
)
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -261,7 +249,6 @@ module.exports = {
)
.addParameter('yesorno', _('Allow moving?'), '', false)
.setDefaultValue('true')
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -278,7 +265,6 @@ module.exports = {
'res/actions/window24.png',
'res/actions/window.png'
)
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -297,7 +283,6 @@ module.exports = {
)
.addParameter('yesorno', _('Allow maximizing?'), '', false)
.setDefaultValue('true')
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -314,7 +299,6 @@ module.exports = {
'res/actions/window24.png',
'res/actions/window.png'
)
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -333,7 +317,6 @@ module.exports = {
)
.addParameter('yesorno', _('Allow minimizing?'), '', false)
.setDefaultValue('true')
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -350,7 +333,6 @@ module.exports = {
'res/actions/window24.png',
'res/actions/window.png'
)
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -369,7 +351,6 @@ module.exports = {
)
.addParameter('yesorno', _('Allow full-screening?'), '', false)
.setDefaultValue('true')
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -386,7 +367,6 @@ module.exports = {
'res/actions/window24.png',
'res/actions/window.png'
)
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -405,7 +385,6 @@ module.exports = {
)
.addParameter('yesorno', _('Allow closing?'), '', false)
.setDefaultValue('true')
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -422,7 +401,6 @@ module.exports = {
'res/actions/window24.png',
'res/actions/window.png'
)
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -464,7 +442,6 @@ module.exports = {
'above the taskbar on Windows. ' +
'This parameter is ignored on linux.'
)
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -481,7 +458,6 @@ module.exports = {
'res/actions/window24.png',
'res/actions/window.png'
)
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -502,7 +478,6 @@ module.exports = {
)
.addParameter('yesorno', _('Enable kiosk mode?'), '', false)
.setDefaultValue('true')
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -519,7 +494,6 @@ module.exports = {
'res/actions/window24.png',
'res/actions/window.png'
)
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -538,7 +512,6 @@ module.exports = {
)
.addParameter('yesorno', _('Enable shadow?'), '', false)
.setDefaultValue('true')
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -555,7 +528,6 @@ module.exports = {
'res/actions/window24.png',
'res/actions/window.png'
)
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -576,7 +548,6 @@ module.exports = {
)
.addParameter('yesorno', _('Enable content protection?'), '', false)
.setDefaultValue('true')
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -595,7 +566,6 @@ module.exports = {
)
.addParameter('yesorno', _('Allow focus?'), '', false)
.setDefaultValue('true')
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -614,7 +584,6 @@ module.exports = {
)
.addParameter('yesorno', _('Flash the window?'), '', false)
.setDefaultValue('true')
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -635,7 +604,6 @@ module.exports = {
.setParameterLongDescription(
'A number between 0 (fully transparent) and 1 (fully opaque).'
)
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -654,7 +622,6 @@ module.exports = {
)
.addParameter('expression', _('X position'), '', false)
.addParameter('expression', _('Y position'), '', false)
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -669,7 +636,6 @@ module.exports = {
_('Windows, Linux, macOS'),
'res/actions/window.png'
)
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -684,7 +650,6 @@ module.exports = {
_('Windows, Linux, macOS'),
'res/actions/window.png'
)
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -701,7 +666,6 @@ module.exports = {
_('Windows, Linux, macOS'),
'res/actions/window.png'
)
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'

View File

@@ -6,23 +6,16 @@ namespace gdjs {
*/
export namespace evtTools {
export namespace advancedWindow {
const getElectronBrowserWindow = (runtimeScene: gdjs.RuntimeScene) => {
const electronRemote = runtimeScene
.getGame()
.getRenderer()
.getElectronRemote();
if (electronRemote) {
return electronRemote.getCurrentWindow();
}
/**
* The game's BrowserWindow instance (or null on
* non-electron platforms).
*/
let electronBrowserWindow: any = null;
return null;
};
export const focus = function (
activate: boolean,
runtimeScene: gdjs.RuntimeScene
) {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
if (typeof require === 'function') {
electronBrowserWindow = require('electron').remote.getCurrentWindow();
}
export const focus = function (activate: boolean) {
if (electronBrowserWindow) {
if (activate) {
electronBrowserWindow.focus();
@@ -32,21 +25,14 @@ namespace gdjs {
}
};
export const isFocused = function (
runtimeScene: gdjs.RuntimeScene
): boolean {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
export const isFocused = function (): boolean {
if (electronBrowserWindow) {
return electronBrowserWindow.isFocused();
}
return false;
};
export const show = function (
activate: boolean,
runtimeScene: gdjs.RuntimeScene
) {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
export const show = function (activate: boolean) {
if (electronBrowserWindow) {
if (activate) {
electronBrowserWindow.showInactive();
@@ -56,21 +42,14 @@ namespace gdjs {
}
};
export const isVisible = function (
runtimeScene: gdjs.RuntimeScene
): boolean {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
export const isVisible = function (): boolean {
if (electronBrowserWindow) {
return electronBrowserWindow.isVisible();
}
return false;
};
export const maximize = function (
activate: boolean,
runtimeScene: gdjs.RuntimeScene
) {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
export const maximize = function (activate: boolean) {
if (electronBrowserWindow) {
if (activate) {
electronBrowserWindow.maximize();
@@ -80,21 +59,14 @@ namespace gdjs {
}
};
export const isMaximized = function (
runtimeScene: gdjs.RuntimeScene
): boolean {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
export const isMaximized = function (): boolean {
if (electronBrowserWindow) {
return electronBrowserWindow.isMaximized();
}
return false;
};
export const minimize = function (
activate: boolean,
runtimeScene: gdjs.RuntimeScene
) {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
export const minimize = function (activate: boolean) {
if (electronBrowserWindow) {
if (activate) {
electronBrowserWindow.minimize();
@@ -104,150 +76,98 @@ namespace gdjs {
}
};
export const isMinimized = function (
runtimeScene: gdjs.RuntimeScene
): boolean {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
export const isMinimized = function (): boolean {
if (electronBrowserWindow) {
return electronBrowserWindow.isMinimized();
}
return false;
};
export const enable = function (
activate: boolean,
runtimeScene: gdjs.RuntimeScene
) {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
export const enable = function (activate: boolean) {
if (electronBrowserWindow) {
electronBrowserWindow.setEnabled(activate);
}
};
export const isEnabled = function (
runtimeScene: gdjs.RuntimeScene
): boolean {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
export const isEnabled = function (): boolean {
if (electronBrowserWindow) {
return electronBrowserWindow.isEnabled();
}
return false;
};
export const setResizable = function (
activate: boolean,
runtimeScene: gdjs.RuntimeScene
) {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
export const setResizable = function (activate: boolean) {
if (electronBrowserWindow) {
electronBrowserWindow.setResizable(activate);
}
};
export const isResizable = function (
runtimeScene: gdjs.RuntimeScene
): boolean {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
export const isResizable = function (): boolean {
if (electronBrowserWindow) {
return electronBrowserWindow.isResizable();
}
return false;
};
export const setMovable = function (
activate: boolean,
runtimeScene: gdjs.RuntimeScene
) {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
export const setMovable = function (activate: boolean) {
if (electronBrowserWindow) {
electronBrowserWindow.setMovable(activate);
}
};
export const isMovable = function (
runtimeScene: gdjs.RuntimeScene
): boolean {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
export const isMovable = function (): boolean {
if (electronBrowserWindow) {
return electronBrowserWindow.isMovable();
}
return false;
};
export const setMaximizable = function (
activate: boolean,
runtimeScene: gdjs.RuntimeScene
) {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
export const setMaximizable = function (activate: boolean) {
if (electronBrowserWindow) {
electronBrowserWindow.setMaximizable(activate);
}
};
export const isMaximizable = function (
runtimeScene: gdjs.RuntimeScene
): boolean {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
export const isMaximizable = function (): boolean {
if (electronBrowserWindow) {
return electronBrowserWindow.isMaximizable();
}
return false;
};
export const setMinimizable = function (
activate: boolean,
runtimeScene: gdjs.RuntimeScene
) {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
export const setMinimizable = function (activate: boolean) {
if (electronBrowserWindow) {
electronBrowserWindow.setMinimizable(activate);
}
};
export const isMinimizable = function (
runtimeScene: gdjs.RuntimeScene
): boolean {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
export const isMinimizable = function (): boolean {
if (electronBrowserWindow) {
return electronBrowserWindow.isMinimizable();
}
return false;
};
export const setFullScreenable = function (
activate: boolean,
runtimeScene: gdjs.RuntimeScene
) {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
export const setFullScreenable = function (activate: boolean) {
if (electronBrowserWindow) {
electronBrowserWindow.setFullScreenable(activate);
}
};
export const isFullScreenable = function (
runtimeScene: gdjs.RuntimeScene
): boolean {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
export const isFullScreenable = function (): boolean {
if (electronBrowserWindow) {
return electronBrowserWindow.isFullScreenable();
}
return false;
};
export const setClosable = function (
activate: boolean,
runtimeScene: gdjs.RuntimeScene
) {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
export const setClosable = function (activate: boolean) {
if (electronBrowserWindow) {
electronBrowserWindow.setClosable(activate);
}
};
export const isClosable = function (
runtimeScene: gdjs.RuntimeScene
): boolean {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
export const isClosable = function (): boolean {
if (electronBrowserWindow) {
return electronBrowserWindow.isClosable();
}
@@ -264,142 +184,93 @@ namespace gdjs {
| 'main-menu'
| 'status'
| 'pop-up-menu'
| 'screen-saver',
runtimeScene: gdjs.RuntimeScene
| 'screen-saver'
) {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
if (electronBrowserWindow) {
electronBrowserWindow.setAlwaysOnTop(activate, level);
}
};
export const isAlwaysOnTop = function (
runtimeScene: gdjs.RuntimeScene
): boolean {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
export const isAlwaysOnTop = function (): boolean {
if (electronBrowserWindow) {
return electronBrowserWindow.isAlwaysOnTop();
}
return false;
};
export const setPosition = function (
x: float,
y: float,
runtimeScene: gdjs.RuntimeScene
) {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
export const setPosition = function (x: float, y: float) {
if (electronBrowserWindow) {
// Convert x and y to (32 bit) integers to avoid Electron errors.
electronBrowserWindow.setPosition(~~x, ~~y);
}
};
export const getPositionX = function (
runtimeScene: gdjs.RuntimeScene
): number {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
export const getPositionX = function (): number {
if (electronBrowserWindow) {
return electronBrowserWindow.getPosition()[0];
}
return 0;
};
export const getPositionY = function (
runtimeScene: gdjs.RuntimeScene
): number {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
export const getPositionY = function (): number {
if (electronBrowserWindow) {
return electronBrowserWindow.getPosition()[1];
}
return 0;
};
export const setKiosk = function (
activate: boolean,
runtimeScene: gdjs.RuntimeScene
) {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
export const setKiosk = function (activate: boolean) {
if (electronBrowserWindow) {
electronBrowserWindow.setKiosk(activate);
}
};
export const isKiosk = function (
runtimeScene: gdjs.RuntimeScene
): boolean {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
export const isKiosk = function (): boolean {
if (electronBrowserWindow) {
return electronBrowserWindow.isKiosk();
}
return false;
};
export const flash = function (
activate: boolean,
runtimeScene: gdjs.RuntimeScene
) {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
export const flash = function (activate: boolean) {
if (electronBrowserWindow) {
electronBrowserWindow.flashFrame(activate);
}
};
export const setHasShadow = function (
activate: boolean,
runtimeScene: gdjs.RuntimeScene
) {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
export const setHasShadow = function (activate: boolean) {
if (electronBrowserWindow) {
electronBrowserWindow.setHasShadow(activate);
}
};
export const hasShadow = function (
runtimeScene: gdjs.RuntimeScene
): boolean {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
export const hasShadow = function (): boolean {
if (electronBrowserWindow) {
return electronBrowserWindow.hasShadow();
}
return false;
};
export const setOpacity = function (
opacity: float,
runtimeScene: gdjs.RuntimeScene
) {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
export const setOpacity = function (opacity: float) {
if (electronBrowserWindow) {
electronBrowserWindow.setOpacity(opacity);
}
};
export const getOpacity = function (
runtimeScene: gdjs.RuntimeScene
): number {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
export const getOpacity = function (): number {
if (electronBrowserWindow) {
return electronBrowserWindow.getOpacity();
}
return 1;
};
export const setContentProtection = function (
activate: boolean,
runtimeScene: gdjs.RuntimeScene
) {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
export const setContentProtection = function (activate: boolean) {
if (electronBrowserWindow) {
electronBrowserWindow.setContentProtection(activate);
}
};
export const setFocusable = function (
activate: boolean,
runtimeScene: gdjs.RuntimeScene
) {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
export const setFocusable = function (activate: boolean) {
if (electronBrowserWindow) {
electronBrowserWindow.setFocusable(activate);
}

View File

@@ -5,9 +5,7 @@ Copyright (c) 2016 Victor Levasseur (victorlevasseur52@gmail.com)
This project is released under the MIT License.
*/
#include "AnchorBehavior.h"
#include <map>
#include "GDCore/CommonTools.h"
#include "GDCore/Project/PropertyDescriptor.h"
#include "GDCore/Serialization/SerializerElement.h"
@@ -22,7 +20,6 @@ void AnchorBehavior::InitializeContent(gd::SerializerElement& content) {
content.SetAttribute("topEdgeAnchor", static_cast<int>(ANCHOR_VERTICAL_NONE));
content.SetAttribute("bottomEdgeAnchor",
static_cast<int>(ANCHOR_VERTICAL_NONE));
content.SetAttribute("useLegacyBottomAndRightAnchors", false);
}
#if defined(GD_IDE_ONLY)
@@ -71,7 +68,7 @@ std::map<gd::String, gd::PropertyDescriptor> AnchorBehavior::GetProperties(
.AddExtraInfo(_("Window left"))
.AddExtraInfo(_("Window right"))
.AddExtraInfo(_("Proportional"))
.SetDescription(_("Anchor the left edge of the object on X axis."));
.SetDescription(_("Use this to anchor the object on X axis."));
properties[_("Right edge anchor")]
.SetValue(GetAnchorAsString(static_cast<HorizontalAnchor>(
@@ -80,8 +77,7 @@ std::map<gd::String, gd::PropertyDescriptor> AnchorBehavior::GetProperties(
.AddExtraInfo(_("No anchor"))
.AddExtraInfo(_("Window left"))
.AddExtraInfo(_("Window right"))
.AddExtraInfo(_("Proportional"))
.SetDescription(_("Anchor the right edge of the object on X axis."));
.AddExtraInfo(_("Proportional"));
properties[_("Top edge anchor")]
.SetValue(GetAnchorAsString(static_cast<VerticalAnchor>(
@@ -91,7 +87,7 @@ std::map<gd::String, gd::PropertyDescriptor> AnchorBehavior::GetProperties(
.AddExtraInfo(_("Window top"))
.AddExtraInfo(_("Window bottom"))
.AddExtraInfo(_("Proportional"))
.SetDescription(_("Anchor the top edge of the object on Y axis."));
.SetDescription(_("Use this to anchor the object on Y axis."));
properties[_("Bottom edge anchor")]
.SetValue(GetAnchorAsString(static_cast<VerticalAnchor>(
@@ -100,20 +96,7 @@ std::map<gd::String, gd::PropertyDescriptor> AnchorBehavior::GetProperties(
.AddExtraInfo(_("No anchor"))
.AddExtraInfo(_("Window top"))
.AddExtraInfo(_("Window bottom"))
.AddExtraInfo(_("Proportional"))
.SetDescription(_("Anchor the bottom edge of the object on Y axis."));
properties[("useLegacyBottomAndRightAnchors")]
.SetLabel(_(
"Stretch object when anchoring right or bottom ledge (deprecated, "
"it's recommended to let this unchecked and anchor both sides if you "
"want Sprite to stretch instead.)"))
.SetGroup(_("Deprecated options (advanced)"))
.SetValue(behaviorContent.GetBoolAttribute(
"useLegacyBottomAndRightAnchors", true)
? "true"
: "false")
.SetType("Boolean");
.AddExtraInfo(_("Proportional"));
return properties;
}
@@ -164,9 +147,6 @@ bool AnchorBehavior::UpdateProperty(gd::SerializerElement& behaviorContent,
behaviorContent.SetAttribute(
"bottomEdgeAnchor",
static_cast<int>(GetVerticalAnchorFromString(value)));
else if (name == "useLegacyBottomAndRightAnchors")
behaviorContent.SetAttribute("useLegacyBottomAndRightAnchors",
(value == "1"));
else
return false;

View File

@@ -15,20 +15,14 @@ namespace gdjs {
_rightEdgeDistance: number = 0;
_topEdgeDistance: number = 0;
_bottomEdgeDistance: number = 0;
_useLegacyBottomAndRightAnchors: boolean = false;
constructor(runtimeScene, behaviorData, owner) {
super(runtimeScene, behaviorData, owner);
this._relativeToOriginalWindowSize =
!!behaviorData.relativeToOriginalWindowSize;
this._relativeToOriginalWindowSize = !!behaviorData.relativeToOriginalWindowSize;
this._leftEdgeAnchor = behaviorData.leftEdgeAnchor;
this._rightEdgeAnchor = behaviorData.rightEdgeAnchor;
this._topEdgeAnchor = behaviorData.topEdgeAnchor;
this._bottomEdgeAnchor = behaviorData.bottomEdgeAnchor;
this._useLegacyBottomAndRightAnchors =
behaviorData.useLegacyBottomAndRightAnchors === undefined
? true
: behaviorData.useLegacyBottomAndRightAnchors;
}
updateFromBehaviorData(oldBehaviorData, newBehaviorData): boolean {
@@ -46,13 +40,6 @@ namespace gdjs {
) {
this._bottomEdgeAnchor = newBehaviorData.bottomEdgeAnchor;
}
if (
oldBehaviorData.useLegacyTrajectory !==
newBehaviorData.useLegacyTrajectory
) {
this._useLegacyBottomAndRightAnchors =
newBehaviorData.useLegacyBottomAndRightAnchors;
}
if (
oldBehaviorData.relativeToOriginalWindowSize !==
newBehaviorData.relativeToOriginalWindowSize
@@ -275,94 +262,28 @@ namespace gdjs {
bottomPixel
);
// Compatibility with GD <= 5.0.133
if (this._useLegacyBottomAndRightAnchors) {
//Move and resize the object according to the anchors
if (
this._rightEdgeAnchor !==
AnchorRuntimeBehavior.HorizontalAnchor.NONE
) {
this.owner.setWidth(bottomRightCoord[0] - topLeftCoord[0]);
}
if (
this._bottomEdgeAnchor !== AnchorRuntimeBehavior.VerticalAnchor.NONE
) {
this.owner.setHeight(bottomRightCoord[1] - topLeftCoord[1]);
}
if (
this._leftEdgeAnchor !== AnchorRuntimeBehavior.HorizontalAnchor.NONE
) {
this.owner.setX(
topLeftCoord[0] + this.owner.getX() - this.owner.getDrawableX()
);
}
if (
this._topEdgeAnchor !== AnchorRuntimeBehavior.VerticalAnchor.NONE
) {
this.owner.setY(
topLeftCoord[1] + this.owner.getY() - this.owner.getDrawableY()
);
}
//Move and resize the object according to the anchors
if (
this._rightEdgeAnchor !== AnchorRuntimeBehavior.HorizontalAnchor.NONE
) {
this.owner.setWidth(bottomRightCoord[0] - topLeftCoord[0]);
}
// End of compatibility code
else {
// Resize if right and left anchors are set
if (
this._rightEdgeAnchor !==
AnchorRuntimeBehavior.HorizontalAnchor.NONE &&
this._leftEdgeAnchor !== AnchorRuntimeBehavior.HorizontalAnchor.NONE
) {
this.owner.setWidth(bottomRightCoord[0] - topLeftCoord[0]);
this.owner.setX(topLeftCoord[0]);
} else {
if (
this._leftEdgeAnchor !==
AnchorRuntimeBehavior.HorizontalAnchor.NONE
) {
this.owner.setX(
topLeftCoord[0] + this.owner.getX() - this.owner.getDrawableX()
);
}
if (
this._rightEdgeAnchor !==
AnchorRuntimeBehavior.HorizontalAnchor.NONE
) {
this.owner.setX(
bottomRightCoord[0] +
this.owner.getX() -
this.owner.getDrawableX() -
this.owner.getWidth()
);
}
}
// Resize if top and bottom anchors are set
if (
this._bottomEdgeAnchor !==
AnchorRuntimeBehavior.VerticalAnchor.NONE &&
this._topEdgeAnchor !== AnchorRuntimeBehavior.VerticalAnchor.NONE
) {
this.owner.setHeight(bottomRightCoord[1] - topLeftCoord[1]);
this.owner.setY(topLeftCoord[1]);
} else {
if (
this._topEdgeAnchor !== AnchorRuntimeBehavior.VerticalAnchor.NONE
) {
this.owner.setY(
topLeftCoord[1] + this.owner.getY() - this.owner.getDrawableY()
);
}
if (
this._bottomEdgeAnchor !==
AnchorRuntimeBehavior.VerticalAnchor.NONE
) {
this.owner.setY(
bottomRightCoord[1] +
this.owner.getY() -
this.owner.getDrawableY() -
this.owner.getHeight()
);
}
}
if (
this._bottomEdgeAnchor !== AnchorRuntimeBehavior.VerticalAnchor.NONE
) {
this.owner.setHeight(bottomRightCoord[1] - topLeftCoord[1]);
}
if (
this._leftEdgeAnchor !== AnchorRuntimeBehavior.HorizontalAnchor.NONE
) {
this.owner.setX(
topLeftCoord[0] + this.owner.getX() - this.owner.getDrawableX()
);
}
if (this._topEdgeAnchor !== AnchorRuntimeBehavior.VerticalAnchor.NONE) {
this.owner.setY(
topLeftCoord[1] + this.owner.getY() - this.owner.getDrawableY()
);
}
}
}

View File

@@ -1,204 +0,0 @@
// @ts-check
describe.only('gdjs.AnchorRuntimeBehavior', function () {
const runtimeGame = new gdjs.RuntimeGame({
variables: [],
resources: { resources: [] },
// @ts-ignore
properties: { windowWidth: 1000, windowHeight: 1000 },
});
const anchorBehaviorName = 'Anchor';
const runtimeScene = new gdjs.RuntimeScene(runtimeGame);
runtimeScene.loadFromScene({
layers: [
{
name: '',
visibility: true,
cameras: [],
effects: [],
ambientLightColorR: 127,
ambientLightColorB: 127,
ambientLightColorG: 127,
isLightingLayer: false,
followBaseLayerCamera: false,
},
],
variables: [],
r: 0,
v: 0,
b: 0,
mangledName: 'Scene1',
name: 'Scene1',
stopSoundsOnStartup: false,
title: '',
behaviorsSharedData: [],
objects: [],
instances: [],
});
function createObject(behaviorProperties) {
const object = new gdjs.TestRuntimeObject(runtimeScene, {
name: 'obj1',
type: '',
behaviors: [
{
name: anchorBehaviorName,
type: 'AnchorBehavior::AnchorBehavior',
// @ts-ignore - properties are not typed
rightEdgeAnchor: 0,
leftEdgeAnchor: 0,
topEdgeAnchor: 0,
bottomEdgeAnchor: 0,
relativeToOriginalWindowSize: true,
useLegacyBottomAndRightAnchors: false,
...behaviorProperties,
},
],
variables: [],
effects: [],
});
object.setCustomWidthAndHeight(10, 10);
runtimeScene.addObject(object);
return object;
}
function getAnchorBehavior(object) {
const behavior = object.getBehavior(anchorBehaviorName);
if (!(behavior instanceof gdjs.AnchorRuntimeBehavior)) {
throw new Error(
'Expected behavior to be an instance of gdjs.AnchorBehavior'
);
}
return behavior;
}
describe('(anchor horizontal edge)', function () {
['rightEdgeAnchor', 'leftEdgeAnchor'].forEach((objectEdge) => {
it(`anchors the ${objectEdge} edge of object to window left (fixed)`, function () {
const object = createObject({ [objectEdge]: 1 });
runtimeGame.setGameResolutionSize(1000, 1000);
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.setGameResolutionSize(2000, 2000);
runtimeScene.renderAndStep(1000 / 60);
expect(object.getX()).to.equal(500);
expect(object.getY()).to.equal(500);
expect(object.getWidth()).to.equal(10);
});
});
['rightEdgeAnchor', 'leftEdgeAnchor'].forEach((objectEdge) => {
it(`anchors the ${objectEdge} edge of object to window right (fixed)`, function () {
const object = createObject({ [objectEdge]: 2 });
runtimeGame.setGameResolutionSize(1000, 1000);
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.setGameResolutionSize(2000, 2000);
runtimeScene.renderAndStep(1000 / 60);
expect(object.getX()).to.equal(1500);
expect(object.getY()).to.equal(500);
expect(object.getWidth()).to.equal(10);
});
});
it('anchors the right and left edge of object (fixed)', function () {
const object = createObject({ leftEdgeAnchor: 1, rightEdgeAnchor: 2 });
runtimeGame.setGameResolutionSize(1000, 1000);
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.setGameResolutionSize(2000, 2000);
runtimeScene.renderAndStep(1000 / 60);
expect(object.getX()).to.equal(500);
expect(object.getY()).to.equal(500);
expect(object.getWidth()).to.equal(1010);
});
it('anchors the left edge of object (proportional)', function () {
const object = createObject({ leftEdgeAnchor: 3 });
runtimeGame.setGameResolutionSize(1000, 1000);
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.setGameResolutionSize(2000, 2000);
runtimeScene.renderAndStep(1000 / 60);
expect(object.getX()).to.equal(1000);
expect(object.getY()).to.equal(500);
expect(object.getWidth()).to.equal(10);
});
});
describe('(anchor vertical edge)', function () {
['topEdgeAnchor', 'bottomEdgeAnchor'].forEach((objectEdge) => {
it(`anchors the ${objectEdge} edge of object to window top (fixed)`, function () {
const object = createObject({ [objectEdge]: 1 });
runtimeGame.setGameResolutionSize(1000, 1000);
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.setGameResolutionSize(2000, 2000);
runtimeScene.renderAndStep(1000 / 60);
expect(object.getX()).to.equal(500);
expect(object.getY()).to.equal(500);
expect(object.getWidth()).to.equal(10);
});
});
['topEdgeAnchor', 'bottomEdgeAnchor'].forEach((objectEdge) => {
it(`anchors the ${objectEdge} edge of object to window bottom (fixed)`, function () {
const object = createObject({ [objectEdge]: 2 });
runtimeGame.setGameResolutionSize(1000, 1000);
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.setGameResolutionSize(2000, 2000);
runtimeScene.renderAndStep(1000 / 60);
expect(object.getX()).to.equal(500);
expect(object.getY()).to.equal(1500);
expect(object.getWidth()).to.equal(10);
});
});
it('anchors the top and bottom edge of object (fixed)', function () {
const object = createObject({ topEdgeAnchor: 1, bottomEdgeAnchor: 2 });
runtimeGame.setGameResolutionSize(1000, 1000);
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.setGameResolutionSize(2000, 2000);
runtimeScene.renderAndStep(1000 / 60);
expect(object.getX()).to.equal(500);
expect(object.getY()).to.equal(500);
expect(object.getHeight()).to.equal(1010);
});
it('anchors the top edge of object (proportional)', function () {
const object = createObject({ topEdgeAnchor: 3 });
runtimeGame.setGameResolutionSize(1000, 1000);
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.setGameResolutionSize(2000, 2000);
runtimeScene.renderAndStep(1000 / 60);
expect(object.getX()).to.equal(500);
expect(object.getY()).to.equal(1000);
expect(object.getWidth()).to.equal(10);
});
});
});

View File

@@ -95,11 +95,10 @@ namespace gdjs {
}
updateFontFamily(): void {
this._pixiObject.textStyles.default.fontFamily =
this._object._runtimeScene
.getGame()
.getFontManager()
.getFontFamily(this._object._fontFamily);
this._pixiObject.textStyles.default.fontFamily = this._object._runtimeScene
.getGame()
.getFontManager()
.getFontFamily(this._object._fontFamily);
this._pixiObject.dirty = true;
}

View File

@@ -169,6 +169,5 @@ namespace gdjs {
return this._pixiObject.textHeight * this.getScale();
}
}
export const BitmapTextRuntimeObjectRenderer =
BitmapTextRuntimeObjectPixiRenderer;
export const BitmapTextRuntimeObjectRenderer = BitmapTextRuntimeObjectPixiRenderer;
}

View File

@@ -4,6 +4,7 @@
# consist in a few lines containing calls to these functions.
macro(gd_add_extension_includes)
include_directories(${sfml_include_dir})
include_directories(${GDCORE_include_dir})
endmacro()
@@ -80,6 +81,7 @@ function(gd_extension_link_libraries target_name)
#Nothing.
ELSE()
target_link_libraries(${target_name} GDCore)
target_link_libraries(${target_name} ${sfml_LIBRARIES})
ENDIF()
endfunction()

View File

@@ -414,8 +414,9 @@ namespace gdjs {
return;
}
if (this.dialogueData.select) {
this.selectedOption =
gdjs.dialogueTree._normalizedOptionIndex(optionIndex);
this.selectedOption = gdjs.dialogueTree._normalizedOptionIndex(
optionIndex
);
this.selectedOptionUpdated = true;
}
};

View File

@@ -7,7 +7,7 @@ This project is released under the MIT License.
#ifndef DRAGGABLEBEHAVIOR_H
#define DRAGGABLEBEHAVIOR_H
#include "GDCore/Vector2.h"
#include <SFML/System/Vector2.hpp>
#include <map>
#include "GDCore/Project/Behavior.h"
#include "GDCore/Project/Object.h"

View File

@@ -52,8 +52,9 @@ namespace gdjs {
const inputManager = runtimeScene.getGame().getInputManager();
//Try mouse
const mouseDraggableManager =
DraggableManager.getMouseManager(runtimeScene);
const mouseDraggableManager = DraggableManager.getMouseManager(
runtimeScene
);
if (
inputManager.isMouseButtonPressed(0) &&
!mouseDraggableManager.isDragging(this)
@@ -106,8 +107,9 @@ namespace gdjs {
}
doStepPostEvents(runtimeScene) {
const mouseDraggableManager =
DraggableManager.getMouseManager(runtimeScene);
const mouseDraggableManager = DraggableManager.getMouseManager(
runtimeScene
);
mouseDraggableManager.leftPressedLastFrame = runtimeScene
.getGame()
.getInputManager()
@@ -172,8 +174,9 @@ namespace gdjs {
if (!runtimeScene.touchDraggableManagers[touchId]) {
//Create the shared manager if necessary.
// @ts-ignore
runtimeScene.touchDraggableManagers[touchId] =
new TouchDraggableManager(runtimeScene, touchId);
runtimeScene.touchDraggableManagers[
touchId
] = new TouchDraggableManager(runtimeScene, touchId);
}
// @ts-ignore
return runtimeScene.touchDraggableManagers[touchId];

View File

@@ -307,7 +307,7 @@ module.exports = {
.setLabel(_('Color map texture for the effect'))
.setDescription(
_(
'You can change colors of pixels by modifing a reference color image, containing each colors, called the *Color Map Texture*. To get started, **download** [a default color map texture here](https://wiki.gdevelop.io/gdevelop5/interface/scene-editor/layer-effects).'
'You can change colors of pixels by modifing a reference color image, containing each colors, called the *Color Map Texture*. To get started, **download** [a default color map texture here](http://wiki.compilgames.net/doku.php/gdevelop5/interface/scene-editor/layer-effects).'
)
);
colorMapProperties
@@ -442,7 +442,7 @@ module.exports = {
.setLabel(_('Displacement map texture'))
.setDescription(
_(
'Displacement map texture for the effect. To get started, **download** [a default displacement map texture here](https://wiki.gdevelop.io/gdevelop5/interface/scene-editor/layer-effects).'
'Displacement map texture for the effect. To get started, **download** [a default displacement map texture here](http://wiki.compilgames.net/doku.php/gdevelop5/interface/scene-editor/layer-effects).'
)
);
displacementProperties

View File

@@ -6,8 +6,7 @@ namespace gdjs {
},
updatePreRender: function (filter, target) {},
updateDoubleParameter: function (filter, parameterName, value) {
const adjustmentFilter =
filter as unknown as PIXI.filters.AdjustmentFilter;
const adjustmentFilter = (filter as unknown) as PIXI.filters.AdjustmentFilter;
if (parameterName === 'gamma') {
adjustmentFilter.gamma = value;
} else if (parameterName === 'saturation') {

View File

@@ -6,8 +6,7 @@ namespace gdjs {
},
updatePreRender: function (filter, target) {},
updateDoubleParameter: function (filter, parameterName, value) {
const advancedBloomFilter =
filter as unknown as PIXI.filters.AdvancedBloomFilter;
const advancedBloomFilter = (filter as unknown) as PIXI.filters.AdvancedBloomFilter;
if (parameterName === 'threshold') {
advancedBloomFilter.threshold = value;
} else if (parameterName === 'bloomScale') {

View File

@@ -6,7 +6,7 @@ namespace gdjs {
},
updatePreRender: function (filter, target) {},
updateDoubleParameter: function (filter, parameterName, value) {
const asciiFilter = filter as unknown as PIXI.filters.AsciiFilter;
const asciiFilter = (filter as unknown) as PIXI.filters.AsciiFilter;
if (parameterName === 'size') {
asciiFilter.size = value;
}

View File

@@ -6,7 +6,7 @@ namespace gdjs {
},
updatePreRender: function (filter, target) {},
updateDoubleParameter: function (filter, parameterName, value) {
const bevelFilter = filter as unknown as PIXI.filters.BevelFilter;
const bevelFilter = (filter as unknown) as PIXI.filters.BevelFilter;
if (parameterName === 'rotation') {
bevelFilter.rotation = value;
} else if (parameterName === 'thickness') {
@@ -21,14 +21,16 @@ namespace gdjs {
}
},
updateStringParameter: function (filter, parameterName, value) {
const bevelFilter = filter as unknown as PIXI.filters.BevelFilter;
const bevelFilter = (filter as unknown) as PIXI.filters.BevelFilter;
if (parameterName === 'lightColor') {
bevelFilter.lightColor =
gdjs.PixiFiltersTools.rgbOrHexToHexNumber(value);
bevelFilter.lightColor = gdjs.PixiFiltersTools.rgbOrHexToHexNumber(
value
);
}
if (parameterName === 'shadowColor') {
bevelFilter.shadowColor =
gdjs.PixiFiltersTools.rgbOrHexToHexNumber(value);
bevelFilter.shadowColor = gdjs.PixiFiltersTools.rgbOrHexToHexNumber(
value
);
}
},
updateBooleanParameter: function (filter, parameterName, value) {},

View File

@@ -9,7 +9,7 @@ namespace gdjs {
updatePreRender: function (filter, target) {},
updateDoubleParameter: function (filter, parameterName, value) {
// @ts-ignore - unsure why PIXI.filters is not recognised.
const colorMatrix = filter as unknown as PIXI.filters.ColorMatrixFilter;
const colorMatrix = (filter as unknown) as PIXI.filters.ColorMatrixFilter;
if (parameterName !== 'opacity') {
return;
}

View File

@@ -8,7 +8,7 @@ namespace gdjs {
updatePreRender: function (filter, target) {},
updateDoubleParameter: function (filter, parameterName, value) {
// @ts-ignore - unsure why PIXI.filters is not recognised.
const blendingModeFilter = filter as unknown as PIXI.filters.AlphaFilter;
const blendingModeFilter = (filter as unknown) as PIXI.filters.AlphaFilter;
if (parameterName === 'alpha') {
blendingModeFilter.alpha = value;
} else if (parameterName === 'blendmode') {

View File

@@ -9,8 +9,7 @@ namespace gdjs {
updatePreRender: function (filter, target) {},
updateDoubleParameter: function (filter, parameterName, value) {
// @ts-ignore - unsure why PIXI.filters is not recognised.
const brightnessFilter =
filter as unknown as PIXI.filters.ColorMatrixFilter;
const brightnessFilter = (filter as unknown) as PIXI.filters.ColorMatrixFilter;
if (parameterName !== 'brightness') {
return;
}

View File

@@ -6,8 +6,7 @@ namespace gdjs {
},
updatePreRender: function (filter, target) {},
updateDoubleParameter: function (filter, parameterName, value) {
const bulgePinchFilter =
filter as unknown as PIXI.filters.BulgePinchFilter;
const bulgePinchFilter = (filter as unknown) as PIXI.filters.BulgePinchFilter;
if (parameterName === 'centerX') {
bulgePinchFilter.center[0] = value;
} else if (parameterName === 'centerY') {

View File

@@ -19,7 +19,7 @@ namespace gdjs {
},
updatePreRender: function (filter, target) {},
updateDoubleParameter: function (filter, parameterName, value) {
const colorMapFilter = filter as unknown as PIXI.filters.ColorMapFilter;
const colorMapFilter = (filter as unknown) as PIXI.filters.ColorMapFilter;
if (parameterName === 'mix') {
colorMapFilter.mix = gdjs.PixiFiltersTools.clampValue(
value / 100,
@@ -30,7 +30,7 @@ namespace gdjs {
},
updateStringParameter: function (filter, parameterName, value) {},
updateBooleanParameter: function (filter, parameterName, value) {
const colorMapFilter = filter as unknown as PIXI.filters.ColorMapFilter;
const colorMapFilter = (filter as unknown) as PIXI.filters.ColorMapFilter;
if (parameterName === 'nearest') {
colorMapFilter.nearest = value;
}

View File

@@ -6,21 +6,21 @@ namespace gdjs {
},
updatePreRender: function (filter, target) {},
updateDoubleParameter: function (filter, parameterName, value) {
const colorReplaceFilter =
filter as unknown as PIXI.filters.ColorReplaceFilter;
const colorReplaceFilter = (filter as unknown) as PIXI.filters.ColorReplaceFilter;
if (parameterName === 'epsilon') {
colorReplaceFilter.epsilon = value;
}
},
updateStringParameter: function (filter, parameterName, value) {
const colorReplaceFilter =
filter as unknown as PIXI.filters.ColorReplaceFilter;
const colorReplaceFilter = (filter as unknown) as PIXI.filters.ColorReplaceFilter;
if (parameterName === 'originalColor') {
colorReplaceFilter.originalColor =
gdjs.PixiFiltersTools.rgbOrHexToHexNumber(value);
colorReplaceFilter.originalColor = gdjs.PixiFiltersTools.rgbOrHexToHexNumber(
value
);
} else if (parameterName === 'newColor') {
colorReplaceFilter.newColor =
gdjs.PixiFiltersTools.rgbOrHexToHexNumber(value);
colorReplaceFilter.newColor = gdjs.PixiFiltersTools.rgbOrHexToHexNumber(
value
);
}
},
updateBooleanParameter: function (filter, parameterName, value) {},

View File

@@ -17,8 +17,7 @@ namespace gdjs {
updatePreRender: function (filter, target) {},
updateDoubleParameter: function (filter, parameterName, value) {
// @ts-ignore - unsure why PIXI.filters is not recognised.
const displacementFilter =
filter as unknown as PIXI.filters.DisplacementFilter;
const displacementFilter = (filter as unknown) as PIXI.filters.DisplacementFilter;
if (parameterName === 'scaleX') {
displacementFilter.scale.x = value;
}

View File

@@ -6,7 +6,7 @@ namespace gdjs {
},
updatePreRender: function (filter, target) {},
updateDoubleParameter: function (filter, parameterName, value) {
const dotFilter = filter as unknown as PIXI.filters.DotFilter;
const dotFilter = (filter as unknown) as PIXI.filters.DotFilter;
if (parameterName === 'scale') {
dotFilter.scale = value;
} else if (parameterName === 'angle') {

View File

@@ -6,8 +6,7 @@ namespace gdjs {
},
updatePreRender: function (filter, target) {},
updateDoubleParameter: function (filter, parameterName, value) {
const dropShadowFilter =
filter as unknown as PIXI.filters.DropShadowFilter;
const dropShadowFilter = (filter as unknown) as PIXI.filters.DropShadowFilter;
if (parameterName === 'blur') {
dropShadowFilter.blur = value;
} else if (parameterName === 'quality') {
@@ -23,16 +22,15 @@ namespace gdjs {
}
},
updateStringParameter: function (filter, parameterName, value) {
const dropShadowFilter =
filter as unknown as PIXI.filters.DropShadowFilter;
const dropShadowFilter = (filter as unknown) as PIXI.filters.DropShadowFilter;
if (parameterName === 'color') {
dropShadowFilter.color =
gdjs.PixiFiltersTools.rgbOrHexToHexNumber(value);
dropShadowFilter.color = gdjs.PixiFiltersTools.rgbOrHexToHexNumber(
value
);
}
},
updateBooleanParameter: function (filter, parameterName, value) {
const dropShadowFilter =
filter as unknown as PIXI.filters.DropShadowFilter;
const dropShadowFilter = (filter as unknown) as PIXI.filters.DropShadowFilter;
if (parameterName === 'shadowOnly') {
dropShadowFilter.shadowOnly = value;
}

View File

@@ -6,7 +6,7 @@ namespace gdjs {
},
updatePreRender: function (filter, target) {},
updateDoubleParameter: function (filter, parameterName, value) {
const glowFilter = filter as unknown as PIXI.filters.GlowFilter;
const glowFilter = (filter as unknown) as PIXI.filters.GlowFilter;
if (parameterName === 'innerStrength') {
glowFilter.innerStrength = value;
} else if (parameterName === 'outerStrength') {
@@ -17,7 +17,7 @@ namespace gdjs {
}
},
updateStringParameter: function (filter, parameterName, value) {
const glowFilter = filter as unknown as PIXI.filters.GlowFilter;
const glowFilter = (filter as unknown) as PIXI.filters.GlowFilter;
if (parameterName === 'color') {
glowFilter.color = gdjs.PixiFiltersTools.rgbOrHexToHexNumber(value);
}

View File

@@ -6,8 +6,7 @@ namespace gdjs {
},
updatePreRender: function (filter, target) {},
updateDoubleParameter: function (filter, parameterName, value) {
const kawaseBlurFilter =
filter as unknown as PIXI.filters.KawaseBlurFilter;
const kawaseBlurFilter = (filter as unknown) as PIXI.filters.KawaseBlurFilter;
if (parameterName === 'pixelizeX') {
// @ts-ignore: fix these wrong parameters
kawaseBlurFilter.pixelizeX = value;

View File

@@ -8,7 +8,7 @@ namespace gdjs {
updatePreRender: function (filter, target) {},
updateDoubleParameter: function (filter, parameterName, value) {
// @ts-ignore - unsure why PIXI.filters is not recognised.
const noiseFilter = filter as unknown as PIXI.filters.NoiseFilter;
const noiseFilter = (filter as unknown) as PIXI.filters.NoiseFilter;
if (parameterName !== 'noise') {
return;
}

View File

@@ -6,7 +6,7 @@ namespace gdjs {
},
updatePreRender: function (filter, target) {},
updateDoubleParameter: function (filter, parameterName, value) {
const outlineFilter = filter as unknown as PIXI.filters.OutlineFilter;
const outlineFilter = (filter as unknown) as PIXI.filters.OutlineFilter;
if (parameterName === 'thickness') {
outlineFilter.thickness = value;
} else if (parameterName === 'padding') {
@@ -14,7 +14,7 @@ namespace gdjs {
}
},
updateStringParameter: function (filter, parameterName, value) {
const outlineFilter = filter as unknown as PIXI.filters.OutlineFilter;
const outlineFilter = (filter as unknown) as PIXI.filters.OutlineFilter;
if (parameterName === 'color') {
outlineFilter.color = gdjs.PixiFiltersTools.rgbOrHexToHexNumber(value);
}

View File

@@ -8,7 +8,7 @@ namespace gdjs {
},
updatePreRender: function (filter, target) {},
updateDoubleParameter: function (filter, parameterName, value) {
const pixelateFilter = filter as unknown as PIXI.filters.PixelateFilter;
const pixelateFilter = (filter as unknown) as PIXI.filters.PixelateFilter;
if (parameterName === 'size') {
pixelateFilter.size = value;
}

View File

@@ -5,8 +5,7 @@ namespace gdjs {
return radialBlurFilter;
},
updatePreRender: function (filter, target) {
const radialBlurFilter =
filter as unknown as PIXI.filters.RadialBlurFilter;
const radialBlurFilter = (filter as unknown) as PIXI.filters.RadialBlurFilter;
radialBlurFilter.center[0] = Math.round(
// @ts-ignore - extra properties are stored on the filter.
radialBlurFilter._centerX * target.getWidth()
@@ -17,8 +16,7 @@ namespace gdjs {
);
},
updateDoubleParameter: function (filter, parameterName, value) {
const radialBlurFilter =
filter as unknown as PIXI.filters.RadialBlurFilter;
const radialBlurFilter = (filter as unknown) as PIXI.filters.RadialBlurFilter;
if (parameterName === 'radius') {
radialBlurFilter.radius = value < 0 ? -1 : value;
} else if (parameterName === 'angle') {

View File

@@ -6,7 +6,7 @@ namespace gdjs {
},
updatePreRender: function (filter, target) {},
updateDoubleParameter: function (filter, parameterName, value) {
const rgbSplitFilter = filter as unknown as PIXI.filters.RGBSplitFilter;
const rgbSplitFilter = (filter as unknown) as PIXI.filters.RGBSplitFilter;
if (parameterName === 'redX') {
rgbSplitFilter.red.x = value;
} else if (parameterName === 'redY') {

View File

@@ -9,8 +9,7 @@ namespace gdjs {
updatePreRender: function (filter, target) {},
updateDoubleParameter: function (filter, parameterName, value) {
// @ts-ignore - unsure why PIXI.filters is not recognised.
const colorMatrixFilter =
filter as unknown as PIXI.filters.ColorMatrixFilter;
const colorMatrixFilter = (filter as unknown) as PIXI.filters.ColorMatrixFilter;
if (parameterName !== 'opacity') {
return;
}

View File

@@ -6,7 +6,7 @@ namespace gdjs {
},
updatePreRender: function (filter, target) {},
updateDoubleParameter: function (filter, parameterName, value) {
const tiltShiftFilter = filter as unknown as PIXI.filters.TiltShiftFilter;
const tiltShiftFilter = (filter as unknown) as PIXI.filters.TiltShiftFilter;
if (parameterName === 'blur') {
tiltShiftFilter.blur = value;
} else if (parameterName === 'gradientBlur') {

View File

@@ -11,7 +11,7 @@ namespace gdjs {
return twistFilter;
},
updatePreRender: function (filter, target) {
const twistFilter = filter as unknown as PIXI.filters.TwistFilter;
const twistFilter = (filter as unknown) as PIXI.filters.TwistFilter;
twistFilter.offset.x = Math.round(
// @ts-ignore - extra properties are stored on the filter.
twistFilter._offsetX * target.getWidth()
@@ -22,7 +22,7 @@ namespace gdjs {
);
},
updateDoubleParameter: function (filter, parameterName, value) {
const twistFilter = filter as unknown as PIXI.filters.TwistFilter;
const twistFilter = (filter as unknown) as PIXI.filters.TwistFilter;
if (parameterName === 'radius') {
twistFilter.radius = value;
} else if (parameterName === 'angle') {

View File

@@ -5,7 +5,7 @@ namespace gdjs {
return zoomBlurFilter;
},
updatePreRender: function (filter, target) {
const zoomBlurFilter = filter as unknown as PIXI.filters.ZoomBlurFilter;
const zoomBlurFilter = (filter as unknown) as PIXI.filters.ZoomBlurFilter;
zoomBlurFilter.center[0] = Math.round(
// @ts-ignore - extra properties are stored on the filter.
zoomBlurFilter._centerX * target.getWidth()
@@ -16,7 +16,7 @@ namespace gdjs {
);
},
updateDoubleParameter: function (filter, parameterName, value) {
const zoomBlurFilter = filter as unknown as PIXI.filters.ZoomBlurFilter;
const zoomBlurFilter = (filter as unknown) as PIXI.filters.ZoomBlurFilter;
if (parameterName === 'centerX') {
// @ts-ignore - extra properties are stored on the filter.
zoomBlurFilter._centerX = value;

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