Compare commits

...

59 Commits

Author SHA1 Message Date
Davy Hélard
d0dd8b8a18 Changes that were in hiding. 2023-07-20 14:40:03 +02:00
Davy Hélard
e60545c146 Remove the objectType attribute from ParameterMetadata and keep the one in ValueTypeMetadata. 2023-07-20 14:40:03 +02:00
Davy Hélard
4225df8203 Revert debug flag. 2023-07-20 14:40:02 +02:00
Davy Hélard
34495bbdb5 Fix GDevelop.js tests. 2023-07-20 14:40:02 +02:00
Davy Hélard
968c6be9d7 Fix Core tests. 2023-07-20 14:40:02 +02:00
Davy Hélard
3b28cc6c63 Fix code generation. 2023-07-20 14:40:01 +02:00
Davy Hélard
8c83677671 WIP: add an ObjectType class. 2023-07-20 14:40:01 +02:00
Davy Hélard
5154936baf Add a component for object capabilities. 2023-07-20 14:40:01 +02:00
Davy Hélard
2311d94207 Declare custom object default capabilities. 2023-07-20 14:40:00 +02:00
Davy Hélard
b47d38d75b Fix dimension expressions. 2023-07-20 14:40:00 +02:00
Davy Hélard
592c5555c3 Fix animations. 2023-07-20 14:40:00 +02:00
Davy Hélard
05671dd8b8 Add a todo. 2023-07-20 14:39:59 +02:00
Davy Hélard
9be969b263 Show expression from capabilities in the list. 2023-07-20 14:39:59 +02:00
Davy Hélard
47835c7a99 Add group icons. 2023-07-20 14:39:59 +02:00
Davy Hélard
aff102e52f Remove SetIncludeFile("runtimeobject.js") 2023-07-20 14:39:59 +02:00
Davy Hélard
715287abef Format 2023-07-20 14:33:34 +02:00
Davy Hélard
3c80a5d7da Fix mewIDE tests. 2023-07-20 14:33:33 +02:00
Davy Hélard
f840a337ce Remove some expression declarations as they could hide the one from the BaseObject. 2023-07-20 14:33:33 +02:00
Davy Hélard
03186b66fb Fix some newIDE tests. 2023-07-20 14:33:33 +02:00
Davy Hélard
483d768962 Make core tests pass. 2023-07-20 14:33:32 +02:00
Davy Hélard
568b2cd129 Fix side effects of suffixing object types with capabilities. 2023-07-20 14:33:32 +02:00
Davy Hélard
d1b2a4d9d2 Filter object selector list. 2023-07-20 14:33:32 +02:00
Davy Hélard
40a194656f Fix instruction search. 2023-07-20 14:33:32 +02:00
Davy Hélard
a8fafef48e Add the animable capability. 2023-07-20 14:33:31 +02:00
Davy Hélard
3cfd831d45 Declare capabilities. 2023-07-20 14:33:31 +02:00
Davy Hélard
b305acddba Declare common instructions for size and scale. 2023-07-20 14:33:31 +02:00
Florian Rival
9e8a15547d Improve leaderboard score handling (#5481)
* Leaderboards will now display the score of the player, if a score was just sent before displaying the leaderboard.
* If the score is being sent, the leaderboard will wait for it to be sent before showing the leaderboard.
* Important change: a player name can now be empty when a score is sent. In this case, the leaderboard will auto-generate a name.
* Leaderboard administration was improved to allow to customise the prefix used to generate automatically player names (when no name is entered by the player). You can also now choose to disallow any custom player name to prevent abuse (in this case, all non-connected player names will be auto-generated)
* Allow to use custom CSS to fully customize the leaderboard - only for business users (reach out if you need this).

Co-authored-by: AlexandreS <32449369+AlexandreSi@users.noreply.github.com>
2023-07-18 16:20:45 +02:00
supertree-wook
ed74a49aa3 Remove unnecessary dependencies in the Editor and GDJS (#5469)
Only show in developer changelog
2023-07-18 14:29:19 +02:00
D8H
6ef5d0c326 Add an action to insert a function parameter (#5483) 2023-07-18 12:29:14 +02:00
AlexandreS
5f871e2643 Fix Safari not being able to open .glb files on iPad/iPhone (#5479) 2023-07-18 09:24:18 +02:00
AlexandreS
4f65fa0d82 Fix: Avoid purchasing twice the same asset pack (#5482) 2023-07-17 17:28:56 +02:00
AlexandreS
4d1d763bd9 Fix keyboard undesired openings on mobile (#5478) 2023-07-13 17:16:37 +02:00
AlexandreS
3286722b6a Enable search and replace in For each object events and Javascript events (#5477) 2023-07-13 17:09:00 +02:00
AlexandreS
656255a662 Bump newIDE version (#5475) 2023-07-12 11:56:23 +02:00
AlexandreS
ea7b7a778e Improve messages visibility in collision masks dialog (#5473)
Don't show in changelog
2023-07-12 10:00:37 +02:00
AlexandreS
9b6de5affd Add possibility to subscribe to a startup plan from the profile (#5472) 2023-07-11 16:31:25 +02:00
Clément Pasteau
0c03659314 Fix Node.js 18 compatibility, upgrade to create-react-app v5 and make mac build universal (#5270)
* only show in developer changelog
2023-07-11 15:03:33 +02:00
github-actions[bot]
6b08c0f033 Update translations [skip ci] (#5466)
Co-authored-by: AlexandreSi <AlexandreSi@users.noreply.github.com>
2023-07-11 14:10:20 +02:00
AlexandreS
a1dcf03a5b Fix the editor hanging when opening a scene with hundreds of instances of 3D model objects (#5470) 2023-07-10 17:31:29 +02:00
D8H
556d13c881 Fix the community warning that wasn't showing up in documentation (#5468)
Don't show in changelog
2023-07-09 19:31:28 +02:00
D8H
0d6c42a9bf Filter private actions and conditions from the reference page (#5467)
* Don't show in changelog
2023-07-07 14:09:53 +02:00
D8H
690ce16ab4 Add a listing of actions and conditions in community extension reference pages (#5464) 2023-07-07 10:50:47 +02:00
github-actions[bot]
5f51a5e465 Update translations [skip ci] (#5465)
Co-authored-by: AlexandreSi <AlexandreSi@users.noreply.github.com>
2023-07-06 09:51:54 +02:00
AlexandreS
b7521de138 Add startup plan support in user profile components (#5462) 2023-07-05 09:39:40 +02:00
AlexandreS
acea6fc595 Fix SetPosition action that was missing parenthesis creating math errors (#5458) 2023-07-03 12:07:10 +02:00
github-actions[bot]
d8107fe3d5 Update translations [skip ci] (#5457)
Co-authored-by: ClementPasteau <ClementPasteau@users.noreply.github.com>
2023-07-03 11:31:55 +02:00
Clément Pasteau
b40b95be99 Remove jimp, use Canvas for image manipulation (#5454)
Do not show in changelog
2023-07-03 11:21:28 +02:00
AlexandreS
6644525dd0 Remove former fix that triggered a bug where values were not persisted after editing expression in event sheet (#5455) 2023-07-03 10:28:43 +02:00
github-actions[bot]
56e66d1c5a Update translations [skip ci] (#5452)
Co-authored-by: ClementPasteau <ClementPasteau@users.noreply.github.com>
2023-06-30 15:51:19 +02:00
Clément Pasteau
90d8afb5a0 Calculate Sprite collision masks automatically (#5447)
* Sprites now have an option to calculate their collision mask automatically, based on the first image of their first animation
* The generated collision mask consists of the biggest rectangle possible, encapsulating the image and avoiding transparent pixels
* This option is enabled by default for all new sprites, and can be disabled to create a custom collision mask like before
* When enabled, the mask will adapt automatically when the first image is updated
2023-06-30 15:33:50 +02:00
AlexandreS
d4db61a595 Fix autofocus of searchbar on tablets in landscape (#5451) 2023-06-29 22:40:06 +02:00
D8H
90413b842d Move event-based extension metadata generation from newIDE to GDJS (#5255) 2023-06-29 20:18:51 +02:00
github-actions[bot]
43c788acbf Update translations [skip ci] (#5444)
Co-authored-by: 4ian <4ian@users.noreply.github.com>
2023-06-29 11:29:17 +02:00
supertree-wook
ee22b2e4b1 Upgrade CMake minimum version and improve CMake code (#5446)
Only show in developer changelog
2023-06-28 12:01:05 +02:00
AlexandreS
007d56e946 Display the scene editors more conveniently on mobile (#5441) 2023-06-26 18:07:23 +02:00
AlexandreS
577c4adb14 Fix images selectors not updating on Box 3D editor after an image has been created with Piskel (#5442) 2023-06-26 17:53:23 +02:00
AlexandreS
7f17720ff3 Fix: Do not close popover when releasing text selection click outside of popover (#5443) 2023-06-23 16:51:24 +02:00
github-actions[bot]
288db1c941 Update translations [skip ci] (#5434)
Co-authored-by: 4ian <4ian@users.noreply.github.com>
2023-06-23 16:32:13 +02:00
Florian Rival
2496fc3eef Revert "Add extension to support Steamworks integration of games made with GDevelop (#5401)" (#5438)
This reverts commit 3c43f28966.
2023-06-22 12:58:00 +02:00
338 changed files with 40571 additions and 43309 deletions

View File

@@ -15,7 +15,7 @@ jobs:
# Build the **entire** app for macOS.
build-macos:
macos:
xcode: 12.5.1
xcode: 14.2.0
steps:
- checkout
@@ -64,11 +64,11 @@ jobs:
# Note: Code signing is done using CSC_LINK (see https://www.electron.build/code-signing).
- run:
name: Build GDevelop IDE
command: export NODE_OPTIONS="--max-old-space-size=7168" && cd newIDE/electron-app && npm run build -- --mac --publish=never
command: export NODE_OPTIONS="--max-old-space-size=7168" && cd newIDE/electron-app && CI=false npm run build -- --mac --publish=never
- run:
name: Clean dist folder to keep only installers/binaries.
command: rm -rf "newIDE/electron-app/dist/mac/GDevelop 5.app" && rm -rf "newIDE/electron-app/dist/mac-arm64/GDevelop 5.app"
command: rm -rf "newIDE/electron-app/dist/mac-universal/GDevelop 5.app"
# Upload artifacts (CircleCI)
- store_artifacts:
@@ -101,8 +101,8 @@ jobs:
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
name: Install Python3 dependencies for Emscripten
command: sudo apt install python-is-python3 python3-distutils -y
- run:
name: Install Emscripten (for GDevelop.js)
@@ -178,8 +178,8 @@ jobs:
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
name: Install Python3 dependencies for Emscripten
command: sudo apt install python-is-python3 python3-distutils -y
- run:
name: Install Emscripten (for GDevelop.js)

View File

@@ -127,7 +127,5 @@
"flow.useNPMPackagedFlow": true,
// Clang format styling (duplicated in scripts/CMakeClangUtils.txt)
"C_Cpp.clang_format_style": "{BasedOnStyle: Google, BinPackParameters: false, BinPackArguments: false}",
"prettier.prettierPath": "./GDJS/node_modules/prettier",
"prettier.configPath": "./GDJS/.prettierrc"
"C_Cpp.clang_format_style": "{BasedOnStyle: Google, BinPackParameters: false, BinPackArguments: false}"
}

View File

@@ -1,100 +1,99 @@
#This is the CMake file used to build GDevelop.
#For more information, see the README.md file.
# This is the CMake file used to build GDevelop.
# For more information, see the README.md file.
cmake_minimum_required(VERSION 2.6)
cmake_policy(SET CMP0011 NEW)
cmake_minimum_required(VERSION 3.5)
# Add utility functions
include(scripts/CMakeClangUtils.txt) # To add clang-format and clang-tidy support to a target
# Macro for defining an option
macro(gd_set_option var default type docstring)
if(NOT DEFINED ${var})
set(${var} ${default})
endif()
set(${var} ${${var}} CACHE ${type} ${docstring} FORCE)
if(NOT DEFINED ${var})
set(${var} ${default})
endif()
set(${var} ${${var}} CACHE ${type} ${docstring} FORCE)
endmacro()
# Set options
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")
# Disable deprecated code
set(NO_GUI TRUE CACHE BOOL "" FORCE) #Force disable old GUI related code.
set(NO_GUI TRUE CACHE BOOL "" FORCE) # Force disable old GUI related code.
#Setting up installation directory, for Linux (has to be done before "project" command).
IF(NOT WIN32)
if (NOT APPLE)
gd_set_option(GD_INSTALL_PREFIX "/opt/gdevelop/" STRING "The directory where GDevelop should be installed")
ELSE()
gd_set_option(GD_INSTALL_PREFIX "." STRING "The directory where GDevelop should be installed")
ENDIF()
# Setting up installation directory, for Linux (has to be done before "project" command).
if(NOT WIN32)
if(NOT APPLE)
gd_set_option(GD_INSTALL_PREFIX "/opt/gdevelop/" STRING "The directory where GDevelop should be installed")
else()
gd_set_option(GD_INSTALL_PREFIX "." STRING "The directory where GDevelop should be installed")
endif()
#As we embed SFML, prevent it to be installed system-wide
# As we embed SFML, prevent it to be installed system-wide
set(CMAKE_INSTALL_PREFIX "${GD_INSTALL_PREFIX}/useless")
ENDIF()
endif()
project(GDevelop)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
IF(NOT WIN32 AND NOT APPLE AND NOT BUILD_TESTS)
SET(CMAKE_SKIP_BUILD_RPATH TRUE) #Avoid errors when packaging for linux.
ENDIF()
IF(APPLE)
if(NOT WIN32 AND NOT APPLE AND NOT BUILD_TESTS)
set(CMAKE_SKIP_BUILD_RPATH TRUE) # Avoid errors when packaging for linux.
endif()
if(APPLE)
set(CMAKE_MACOSX_RPATH 1)
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE)
set(CMAKE_INSTALL_RPATH ".")
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_WCHAR_H_CPLUSPLUS_98_CONFORMANCE_")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-potentially-evaluated-expression")
ENDIF()
#Sanity checks
IF ("${CMAKE_BUILD_TYPE}" STREQUAL "")
message( "CMAKE_BUILD_TYPE is empty, assuming build type is Release" )
add_compile_options(
-D_WCHAR_H_CPLUSPLUS_98_CONFORMANCE_
-Wno-potentially-evaluated-expression)
endif()
# Sanity checks
if("${CMAKE_BUILD_TYPE}" STREQUAL "")
message(STATUS "CMAKE_BUILD_TYPE is empty, assuming build type is Release")
set(CMAKE_BUILD_TYPE Release)
ENDIF()
endif()
IF("${CMAKE_BUILD_TYPE}" STREQUAL "Release" AND NOT WIN32 AND CMAKE_COMPILER_IS_GNUCXX)
SET(CMAKE_SHARED_LINKER_FLAGS "-s") #Force stripping to avoid errors when packaging for linux.
ENDIF()
if("${CMAKE_BUILD_TYPE}" STREQUAL "Release" AND NOT WIN32 AND CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_SHARED_LINKER_FLAGS "-s") # Force stripping to avoid errors when packaging for linux.
endif()
#Activate C++11
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=gnu++11" COMPILER_SUPPORTS_CXX11)
CHECK_CXX_COMPILER_FLAG("-std=gnu++0x" COMPILER_SUPPORTS_CXX0X)
if(COMPILER_SUPPORTS_CXX11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")
elseif(COMPILER_SUPPORTS_CXX0X)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++0x")
else()
message(FATAL_ERROR "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support (with GNU extensions). Please use a different C++ compiler.")
endif()
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Mark some warnings as errors
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
# Activate as much warnings as possible to avoid errors like
# uninitialized variables or other hard to debug bugs.
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unknown-warning-option")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-reorder-ctor -Wno-reorder -Wno-pessimizing-move -Wno-unused-variable -Wno-unused-private-field")
add_compile_options(
-Wall
-Wno-unknown-warning-option
-Wno-reorder-ctor
-Wno-reorder
-Wno-pessimizing-move
-Wno-unused-variable
-Wno-unused-private-field
# Make as much warnings considered as errors as possible (only one for now).
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror=return-stack-address")
# Make as much warnings considered as errors as possible (only one for now).
-Werror=return-stack-address)
endif()
#Define common directories:
# Define common directories:
set(GD_base_dir ${CMAKE_CURRENT_SOURCE_DIR})
#Add all the CMakeLists:
ADD_SUBDIRECTORY(ExtLibs)
IF(BUILD_CORE)
ADD_SUBDIRECTORY(Core)
ENDIF()
IF(BUILD_GDJS)
ADD_SUBDIRECTORY(GDJS)
ENDIF()
IF(EMSCRIPTEN)
ADD_SUBDIRECTORY(GDevelop.js)
ENDIF()
IF(BUILD_EXTENSIONS)
ADD_SUBDIRECTORY(Extensions)
ENDIF()
# Add all the CMakeLists:
add_subdirectory(ExtLibs)
if(BUILD_CORE)
add_subdirectory(Core)
endif()
if(BUILD_GDJS)
add_subdirectory(GDJS)
endif()
if(EMSCRIPTEN)
add_subdirectory(GDevelop.js)
endif()
if(BUILD_EXTENSIONS)
add_subdirectory(Extensions)
endif()

View File

@@ -1,83 +1,98 @@
cmake_minimum_required(VERSION 2.6)
cmake_policy(SET CMP0015 NEW)
cmake_minimum_required(VERSION 3.5)
project(GDCore)
SET(CMAKE_C_USE_RESPONSE_FILE_FOR_OBJECTS 1) #Force use response file: useful for Ninja build system on Windows.
SET(CMAKE_CXX_USE_RESPONSE_FILE_FOR_OBJECTS 1)
SET(CMAKE_C_USE_RESPONSE_FILE_FOR_INCLUDES 1)
SET(CMAKE_CXX_USE_RESPONSE_FILE_FOR_INCLUDES 1)
set(CMAKE_C_USE_RESPONSE_FILE_FOR_OBJECTS 1) # Force use response file: useful for Ninja build system on Windows.
set(CMAKE_CXX_USE_RESPONSE_FILE_FOR_OBJECTS 1)
set(CMAKE_C_USE_RESPONSE_FILE_FOR_INCLUDES 1)
set(CMAKE_CXX_USE_RESPONSE_FILE_FOR_INCLUDES 1)
#Define common directories:
# Define common directories:
set(GDCORE_include_dir ${GD_base_dir}/Core PARENT_SCOPE)
set(GDCORE_lib_dir ${GD_base_dir}/Binaries/Output/${CMAKE_BUILD_TYPE}_${CMAKE_SYSTEM_NAME} PARENT_SCOPE)
#Dependencies on external libraries:
###
# Dependencies on external libraries:
#
#Defines
###
add_definitions( -DGD_IDE_ONLY )
IF (EMSCRIPTEN)
add_definitions( -DEMSCRIPTEN )
ENDIF()
IF(CMAKE_BUILD_TYPE MATCHES "Debug")
add_definitions( -DDEBUG )
ELSE()
add_definitions( -DRELEASE )
ENDIF()
# Defines
#
add_definitions(-DGD_IDE_ONLY)
if(EMSCRIPTEN)
add_definitions(-DEMSCRIPTEN)
endif()
if("${CMAKE_BUILD_TYPE}" MATCHES "Debug")
add_definitions(-DDEBUG)
else()
add_definitions(-DRELEASE)
endif()
IF(WIN32)
add_definitions( -DWINDOWS )
add_definitions( "-DGD_CORE_API=__declspec(dllexport)" )
add_definitions( -D__GNUWIN32__ )
ELSE()
IF(APPLE)
add_definitions( -DMACOS )
ELSE()
add_definitions( -DLINUX )
ENDIF()
add_definitions( -DGD_API= )
add_definitions( -DGD_CORE_API= )
ENDIF(WIN32)
if(WIN32)
add_definitions(-DWINDOWS)
add_definitions("-DGD_CORE_API=__declspec(dllexport)")
add_definitions(-D__GNUWIN32__)
else()
if(APPLE)
add_definitions(-DMACOS)
else()
add_definitions(-DLINUX)
endif()
add_definitions(-DGD_API=)
add_definitions(-DGD_CORE_API=)
endif()
#The target
###
# The target
#
include_directories(.)
file(GLOB_RECURSE source_files GDCore/*)
file(
GLOB_RECURSE
source_files
GDCore/*)
file(GLOB_RECURSE formatted_source_files tests/* GDCore/Events/* GDCore/Extensions/* GDCore/IDE/* GDCore/Project/* GDCore/Serialization/* GDCore/Tools/*)
list(REMOVE_ITEM formatted_source_files "${CMAKE_CURRENT_SOURCE_DIR}/GDCore/IDE/Dialogs/GDCoreDialogs.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/GDCore/IDE/Dialogs/GDCoreDialogs.h" "${CMAKE_CURRENT_SOURCE_DIR}/GDCore/IDE/Dialogs/GDCoreDialogs_dialogs_bitmaps.cpp")
file(
GLOB_RECURSE
formatted_source_files
tests/*
GDCore/Events/*
GDCore/Extensions/*
GDCore/IDE/*
GDCore/Project/*
GDCore/Serialization/*
GDCore/Tools/*)
list(
REMOVE_ITEM
formatted_source_files
"${CMAKE_CURRENT_SOURCE_DIR}/GDCore/IDE/Dialogs/GDCoreDialogs.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/GDCore/IDE/Dialogs/GDCoreDialogs.h"
"${CMAKE_CURRENT_SOURCE_DIR}/GDCore/IDE/Dialogs/GDCoreDialogs_dialogs_bitmaps.cpp")
gd_add_clang_utils(GDCore "${formatted_source_files}")
IF(EMSCRIPTEN)
if(EMSCRIPTEN)
# Emscripten treats all libraries as static libraries
add_library(GDCore STATIC ${source_files})
ELSE()
else()
add_library(GDCore SHARED ${source_files})
ENDIF()
IF(EMSCRIPTEN)
endif()
if(EMSCRIPTEN)
set_target_properties(GDCore PROPERTIES SUFFIX ".bc")
ELSEIF(WIN32)
elseif(WIN32)
set_target_properties(GDCore PROPERTIES PREFIX "")
ELSE()
else()
set_target_properties(GDCore PROPERTIES PREFIX "lib")
ENDIF()
endif()
set(LIBRARY_OUTPUT_PATH ${GD_base_dir}/Binaries/Output/${CMAKE_BUILD_TYPE}_${CMAKE_SYSTEM_NAME})
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})
#Tests
###
# Tests
#
if(BUILD_TESTS)
file(
GLOB_RECURSE
test_source_files
tests/*
)
GLOB_RECURSE
test_source_files
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.
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})
endif()

View File

@@ -15,7 +15,7 @@ using namespace std;
namespace gd {
ForEachEvent::ForEachEvent()
: BaseEvent(), objectsToPick(""), objectsToPickSelected(false) {}
: BaseEvent(), objectsToPick("") {}
vector<gd::InstructionsList*> ForEachEvent::GetAllConditionsVectors() {
vector<gd::InstructionsList*> allConditions;

View File

@@ -6,6 +6,8 @@
#ifndef FOREACHEVENT_H
#define FOREACHEVENT_H
#include <vector>
#include "GDCore/Events/Event.h"
#include "GDCore/Events/EventsList.h"
namespace gd {
@@ -62,13 +64,17 @@ class GD_CORE_API ForEachEvent : public gd::BaseEvent {
virtual void UnserializeFrom(gd::Project& project,
const SerializerElement& element);
std::vector<gd::Expression*> GetAllObjectExpressions() {
std::vector<gd::Expression*> allObjectExpressions;
allObjectExpressions.push_back(&objectsToPick);
return allObjectExpressions;
}
private:
gd::Expression objectsToPick;
gd::InstructionsList conditions;
gd::InstructionsList actions;
gd::EventsList events;
bool objectsToPickSelected;
};
} // namespace gd

View File

@@ -267,11 +267,11 @@ gd::String EventsCodeGenerator::GenerateConditionCode(
return "/* Unknown instruction - skipped. */";
}
AddIncludeFiles(instrInfos.codeExtraInformation.GetIncludeFiles());
AddIncludeFiles(instrInfos.GetIncludeFiles());
maxConditionsListsSize =
std::max(maxConditionsListsSize, condition.GetSubInstructions().size());
if (instrInfos.codeExtraInformation.HasCustomCodeGenerator()) {
if (instrInfos.HasCustomCodeGenerator()) {
context.EnterCustomCondition();
conditionCode += instrInfos.codeExtraInformation.customCodeGenerator(
condition, *this, context);
@@ -295,17 +295,17 @@ gd::String EventsCodeGenerator::GenerateConditionCode(
gd::String objectInParameter =
condition.GetParameter(pNb).GetPlainString();
auto& parameterObjectType = instrInfos.parameters[pNb].GetValueTypeMetadata().GetObjectType().GetName();
if (!GetObjectsAndGroups().HasObjectNamed(objectInParameter) &&
!GetGlobalObjectsAndGroups().HasObjectNamed(objectInParameter) &&
!GetObjectsAndGroups().GetObjectGroups().Has(objectInParameter) &&
!GetGlobalObjectsAndGroups().GetObjectGroups().Has(
objectInParameter)) {
return "/* Unknown object - skipped. */";
} else if (!instrInfos.parameters[pNb].GetExtraInfo().empty() &&
} else if (!parameterObjectType.empty() && parameterObjectType !=
gd::GetTypeOfObject(GetGlobalObjectsAndGroups(),
GetObjectsAndGroups(),
objectInParameter) !=
instrInfos.parameters[pNb].GetExtraInfo()) {
objectInParameter)) {
return "/* Mismatched object type - skipped. */";
}
}
@@ -323,11 +323,8 @@ gd::String EventsCodeGenerator::GenerateConditionCode(
const ObjectMetadata& objInfo =
MetadataProvider::GetObjectMetadata(platform, objectType);
if (objInfo.IsUnsupportedBaseObjectCapability(
if (objInfo.IsSupportedBaseObjectCapability(
instrInfos.GetRequiredBaseObjectCapability())) {
conditionCode +=
"/* Object with unsupported capability - skipped. */\n";
} else {
AddIncludeFiles(objInfo.includeFiles);
context.SetCurrentObject(realObjects[i]);
context.ObjectsListNeeded(realObjects[i]);
@@ -344,6 +341,9 @@ gd::String EventsCodeGenerator::GenerateConditionCode(
context);
context.SetNoCurrentObject();
} else {
conditionCode +=
"/* Object with unsupported capability - skipped. */\n";
}
}
}
@@ -459,9 +459,9 @@ gd::String EventsCodeGenerator::GenerateActionCode(
return "/* Unknown instruction - skipped. */";
}
AddIncludeFiles(instrInfos.codeExtraInformation.GetIncludeFiles());
AddIncludeFiles(instrInfos.GetIncludeFiles());
if (instrInfos.codeExtraInformation.HasCustomCodeGenerator()) {
if (instrInfos.HasCustomCodeGenerator()) {
return instrInfos.codeExtraInformation.customCodeGenerator(
action, *this, context);
}
@@ -485,17 +485,18 @@ gd::String EventsCodeGenerator::GenerateActionCode(
for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
if (ParameterMetadata::IsObject(instrInfos.parameters[pNb].GetType())) {
gd::String objectInParameter = action.GetParameter(pNb).GetPlainString();
auto& parameterObjectType = instrInfos.parameters[pNb].GetValueTypeMetadata().GetObjectType().GetName();
if (!GetObjectsAndGroups().HasObjectNamed(objectInParameter) &&
!GetGlobalObjectsAndGroups().HasObjectNamed(objectInParameter) &&
!GetObjectsAndGroups().GetObjectGroups().Has(objectInParameter) &&
!GetGlobalObjectsAndGroups().GetObjectGroups().Has(
objectInParameter)) {
return "/* Unknown object - skipped. */";
} else if (!instrInfos.parameters[pNb].GetExtraInfo().empty() &&
} else if (!parameterObjectType.empty() && parameterObjectType !=
gd::GetTypeOfObject(GetGlobalObjectsAndGroups(),
GetObjectsAndGroups(),
objectInParameter) !=
instrInfos.parameters[pNb].GetExtraInfo()) {
objectInParameter)) {
return "/* Mismatched object type - skipped. */";
}
}
@@ -515,10 +516,8 @@ gd::String EventsCodeGenerator::GenerateActionCode(
const ObjectMetadata& objInfo =
MetadataProvider::GetObjectMetadata(platform, objectType);
if (objInfo.IsUnsupportedBaseObjectCapability(
if (objInfo.IsSupportedBaseObjectCapability(
instrInfos.GetRequiredBaseObjectCapability())) {
actionCode += "/* Object with unsupported capability - skipped. */\n";
} else {
AddIncludeFiles(objInfo.includeFiles);
context.SetCurrentObject(realObjects[i]);
context.ObjectsListNeeded(realObjects[i]);
@@ -535,6 +534,8 @@ gd::String EventsCodeGenerator::GenerateActionCode(
optionalAsyncCallbackName);
context.SetNoCurrentObject();
} else {
actionCode += "/* Object with unsupported capability - skipped. */\n";
}
}
}
@@ -1057,7 +1058,7 @@ gd::String EventsCodeGenerator::GenerateObjectCondition(
// Prepare call
// Add a static_cast if necessary
gd::String objectFunctionCallNamePart =
(!instrInfos.parameters[0].GetExtraInfo().empty())
(!instrInfos.parameters[0].GetValueTypeMetadata().GetObjectType().IsBaseObject())
? "static_cast<" + objInfo.className + "*>(" +
GetObjectListName(objectName, context) + "[i])->" +
instrInfos.codeExtraInformation.functionCallName

View File

@@ -216,10 +216,10 @@ gd::String ExpressionCodeGenerator::GenerateFreeFunctionCode(
const std::vector<std::unique_ptr<ExpressionNode>>& parameters,
const ExpressionMetadata& expressionMetadata) {
codeGenerator.AddIncludeFiles(
expressionMetadata.codeExtraInformation.GetIncludeFiles());
expressionMetadata.GetIncludeFiles());
// Launch custom code generator if needed
if (expressionMetadata.codeExtraInformation.HasCustomCodeGenerator()) {
if (expressionMetadata.HasCustomCodeGenerator()) {
return expressionMetadata.codeExtraInformation.customCodeGenerator(
PrintParameters(parameters), codeGenerator, context);
}
@@ -242,10 +242,10 @@ gd::String ExpressionCodeGenerator::GenerateObjectFunctionCode(
codeGenerator.GetObjectsAndGroups();
codeGenerator.AddIncludeFiles(
expressionMetadata.codeExtraInformation.GetIncludeFiles());
expressionMetadata.GetIncludeFiles());
// Launch custom code generator if needed
if (expressionMetadata.codeExtraInformation.HasCustomCodeGenerator()) {
if (expressionMetadata.HasCustomCodeGenerator()) {
return expressionMetadata.codeExtraInformation.customCodeGenerator(
PrintParameters(parameters), codeGenerator, context);
}
@@ -270,11 +270,8 @@ gd::String ExpressionCodeGenerator::GenerateObjectFunctionCode(
const ObjectMetadata& objInfo = MetadataProvider::GetObjectMetadata(
codeGenerator.GetPlatform(), objectType);
if (objInfo.IsUnsupportedBaseObjectCapability(
if (objInfo.IsSupportedBaseObjectCapability(
expressionMetadata.GetRequiredBaseObjectCapability())) {
// Do nothing, skipping objects not supporting the capability required by
// this expression.
} else {
codeGenerator.AddIncludeFiles(objInfo.includeFiles);
functionOutput = codeGenerator.GenerateObjectFunctionCall(
realObjects[i],
@@ -283,6 +280,9 @@ gd::String ExpressionCodeGenerator::GenerateObjectFunctionCode(
parametersCode,
functionOutput,
context);
} else {
// Do nothing, skipping objects not supporting the capability required by
// this expression.
}
}
@@ -300,10 +300,10 @@ gd::String ExpressionCodeGenerator::GenerateBehaviorFunctionCode(
codeGenerator.GetObjectsAndGroups();
codeGenerator.AddIncludeFiles(
expressionMetadata.codeExtraInformation.GetIncludeFiles());
expressionMetadata.GetIncludeFiles());
// Launch custom code generator if needed
if (expressionMetadata.codeExtraInformation.HasCustomCodeGenerator()) {
if (expressionMetadata.HasCustomCodeGenerator()) {
return expressionMetadata.codeExtraInformation.customCodeGenerator(
PrintParameters(parameters), codeGenerator, context);
}

View File

@@ -282,6 +282,14 @@ class GD_CORE_API BaseEvent {
*/
bool IsFolded() const { return folded; }
/**
* \brief Return a list of all objects linked to the event.
*/
virtual std::vector<gd::Expression*> GetAllObjectExpressions() {
std::vector<gd::Expression*> allObjectExpressions;
return allObjectExpressions;
}
///@}
std::weak_ptr<gd::BaseEvent>

View File

@@ -17,7 +17,7 @@ const gd::String& EventsCodeNameMangler::GetMangledObjectsListName(
return it->second;
}
gd::String partiallyMangledName = originalObjectName;
gd::String partiallyMangledName = GetMangledNameWithForbiddenUnderscore(originalObjectName);
static const gd::String allowedCharacters =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
@@ -43,7 +43,15 @@ const gd::String& EventsCodeNameMangler::GetExternalEventsFunctionMangledName(
return it->second;
}
gd::String partiallyMangledName = externalEventsName;
gd::String partiallyMangledName = GetMangledNameWithForbiddenUnderscore(externalEventsName);
mangledExternalEventsNames[externalEventsName] = "GDExternalEvents" + partiallyMangledName;
return mangledExternalEventsNames[externalEventsName];
}
gd::String EventsCodeNameMangler::GetMangledNameWithForbiddenUnderscore(
const gd::String &name) {
gd::String partiallyMangledName = name;
static const gd::String allowedCharacters =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
@@ -57,11 +65,30 @@ const gd::String& EventsCodeNameMangler::GetExternalEventsFunctionMangledName(
partiallyMangledName.replace(i, 1, "_" + gd::String::From(unallowedChar));
}
}
mangledExternalEventsNames[externalEventsName] = "GDExternalEvents" + partiallyMangledName;
return mangledExternalEventsNames[externalEventsName];
return partiallyMangledName;
}
gd::String EventsCodeNameMangler::GetMangledName(
const gd::String &name) {
gd::String partiallyMangledName = name;
static const gd::String allowedCharacters =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_";
for (size_t i = 0; i < partiallyMangledName.size();
++i) // Replace all unallowed letter by an underscore and the ascii
// number of the letter
{
if (allowedCharacters.find_first_of(
std::u32string(1, partiallyMangledName[i])) == gd::String::npos) {
char32_t unallowedChar = partiallyMangledName[i];
partiallyMangledName.replace(i, 1, "_" + gd::String::From(unallowedChar));
}
}
return partiallyMangledName;
}
const gd::String& ManObjListName(const gd::String &objectName) {
return EventsCodeNameMangler::Get()->GetMangledObjectsListName(objectName);
}

View File

@@ -36,6 +36,8 @@ class GD_CORE_API EventsCodeNameMangler {
const gd::String &GetExternalEventsFunctionMangledName(
const gd::String &externalEventsName);
static gd::String GetMangledName(const gd::String &name);
static EventsCodeNameMangler *Get();
static void DestroySingleton();
@@ -44,6 +46,9 @@ class GD_CORE_API EventsCodeNameMangler {
virtual ~EventsCodeNameMangler(){};
static EventsCodeNameMangler *_singleton;
// This method is inlined to avoid to copy the returned string.
static inline gd::String GetMangledNameWithForbiddenUnderscore(const gd::String &name);
std::unordered_map<gd::String, gd::String>
mangledObjectNames; ///< Memoized results of mangling for objects
std::unordered_map<gd::String, gd::String>

View File

@@ -29,8 +29,20 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.SetIcon("res/actions/force24.png");
extension.AddInstructionOrExpressionGroupMetadata(_("Variables"))
.SetIcon("res/conditions/var24.png");
extension.AddInstructionOrExpressionGroupMetadata(_("Timers"))
.SetIcon("res/actions/timer24.png");
extension.AddInstructionOrExpressionGroupMetadata(_("Visibility"))
.SetIcon("res/actions/visibilite24.png");
extension.AddInstructionOrExpressionGroupMetadata(_("Position"))
.SetIcon("res/actions/position24_black.png");
extension.AddInstructionOrExpressionGroupMetadata(_("Angle"))
.SetIcon("res/actions/direction24_black.png");
extension.AddInstructionOrExpressionGroupMetadata(_("Size"))
.SetIcon("res/actions/scale24_black.png");
extension.AddInstructionOrExpressionGroupMetadata(_("Scale"))
.SetIcon("res/actions/scale24_black.png");
extension.AddInstructionOrExpressionGroupMetadata(_("Animations and images"))
.SetIcon("res/conditions/animation24.png");
gd::ObjectMetadata& obj = extension.AddObject<gd::ObjectConfiguration>(
"", _("Base object"), _("Base object"), "res/objeticon24.png");
@@ -1101,6 +1113,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/actions/scaleWidth_black.png")
.AddParameter("object", _("Object"));
// Deprecated
obj.AddExpression("Largeur",
_("Width"),
_("Width of the object"),
@@ -1116,6 +1129,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/actions/scaleHeight_black.png")
.AddParameter("object", _("Object"));
// Deprecated
obj.AddExpression("Hauteur",
_("Height"),
_("Height of the object"),
@@ -1201,7 +1215,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
obj.AddExpression("ObjectTimerElapsedTime",
_("Object timer value"),
_("Value of an object timer"),
_("Object timers"),
_("Timers"),
"res/actions/time.png")
.AddParameter("object", _("Object"))
.AddParameter("identifier", _("Timer's name"), "objectTimer");
@@ -1262,7 +1276,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("objectEffectName", _("Effect name"))
.AddParameter("yesorno", _("Enable?"))
.MarkAsSimple()
.SetRequiresBaseObjectCapability("effect");
.SetRequiredBaseObjectCapability("effect");
obj.AddAction("SetEffectDoubleParameter",
_("Effect parameter (number)"),
@@ -1278,7 +1292,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("objectEffectParameterName", _("Parameter name"))
.AddParameter("expression", _("New value"))
.MarkAsSimple()
.SetRequiresBaseObjectCapability("effect");
.SetRequiredBaseObjectCapability("effect");
obj.AddAction("SetEffectStringParameter",
_("Effect parameter (string)"),
@@ -1295,7 +1309,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("objectEffectParameterName", _("Parameter name"))
.AddParameter("string", _("New value"))
.MarkAsSimple()
.SetRequiresBaseObjectCapability("effect");
.SetRequiredBaseObjectCapability("effect");
obj.AddAction("SetEffectBooleanParameter",
_("Effect parameter (enable or disable)"),
@@ -1311,7 +1325,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("objectEffectParameterName", _("Parameter name"))
.AddParameter("yesorno", _("Enable?"))
.MarkAsSimple()
.SetRequiresBaseObjectCapability("effect");
.SetRequiredBaseObjectCapability("effect");
obj.AddCondition("IsEffectEnabled",
_("Effect is enabled"),
@@ -1323,7 +1337,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("object", _("Object"))
.AddParameter("objectEffectName", _("Effect name"))
.MarkAsSimple()
.SetRequiresBaseObjectCapability("effect");
.SetRequiredBaseObjectCapability("effect");
obj.AddAction("SetIncludedInParentCollisionMask",
_("Include in parent collision mask"),
@@ -1668,6 +1682,297 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"",
"res/actions/layer.png")
.AddParameter("object", _("Object"));
// Instruction for Resizable capability.
{
obj.AddAction("SetWidth",
_("Width"),
_("Change the width of the object."),
_("the width"),
_("Size"),
"res/actions/scaleWidth24_black.png",
"res/actions/scaleWidth_black.png")
.AddParameter("object", _("Object"))
.AddRequiredObjectCapabilityOnLastParameter("resizable")
.UseStandardOperatorParameters("number",
ParameterOptions::MakeNewOptions())
.SetRequiredBaseObjectCapability("resizable")
.MarkAsAdvanced();
obj.AddCondition("Width",
_("Width"),
_("Compare the width of the object."),
_("the width"),
_("Size"),
"res/conditions/scaleWidth24_black.png",
"res/conditions/scaleWidth_black.png")
.AddParameter("object", _("Object"))
.AddRequiredObjectCapabilityOnLastParameter("resizable")
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions())
.SetRequiredBaseObjectCapability("resizable")
.MarkAsAdvanced();
obj.AddAction("SetHeight",
_("Height"),
_("Change the height of the object."),
_("the height"),
_("Size"),
"res/actions/scaleHeight24_black.png",
"res/actions/scaleHeight_black.png")
.AddParameter("object", _("Object"))
.AddRequiredObjectCapabilityOnLastParameter("resizable")
.UseStandardOperatorParameters("number",
ParameterOptions::MakeNewOptions())
.SetRequiredBaseObjectCapability("resizable")
.MarkAsAdvanced();
obj.AddCondition("Height",
_("Height"),
_("Compare the height of the object."),
_("the height"),
_("Size"),
"res/conditions/scaleHeight24_black.png",
"res/conditions/scaleHeight_black.png")
.AddParameter("object", _("Object"))
.AddRequiredObjectCapabilityOnLastParameter("resizable")
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions())
.SetRequiredBaseObjectCapability("resizable")
.MarkAsAdvanced();
obj.AddAction("SetSize",
_("Size"),
_("Change the size of an object."),
_("Change the size of _PARAM0_: set to _PARAM1_ x _PARAM2_"),
_("Size"),
"res/actions/scale24_black.png",
"res/actions/scale_black.png")
.AddParameter("object", _("Object"))
.AddRequiredObjectCapabilityOnLastParameter("resizable")
.AddParameter("expression", _("Width"))
.AddParameter("expression", _("Height"))
.SetRequiredBaseObjectCapability("resizable")
.MarkAsAdvanced();
}
// Instruction for Scalable capability.
{
obj.AddExpressionAndConditionAndAction(
"number",
"Scale",
_("Scale"),
_("the scale of the object (default scale is 1)"),
_("the scale"),
_("Scale"),
"res/actions/scale24_black.png")
.AddParameter("object", _("Object"))
.AddRequiredObjectCapabilityOnLastParameter("scalable")
.UseStandardParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Scale (1 by default)")))
.SetRequiredBaseObjectCapability("scalable")
.MarkAsAdvanced();
obj.AddExpressionAndConditionAndAction(
"number",
"ScaleX",
_("Scale on X axis"),
_("the scale on X axis of the object (default scale is 1)"),
_("the scale on X axis"),
_("Scale"),
"res/actions/scale24_black.png")
.AddParameter("object", _("Object"))
.AddRequiredObjectCapabilityOnLastParameter("scalable")
.UseStandardParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Scale (1 by default)")))
.SetRequiredBaseObjectCapability("scalable")
.MarkAsAdvanced();
obj.AddExpressionAndConditionAndAction(
"number",
"ScaleY",
_("Scale on Y axis"),
_("the scale on Y axis of the object (default scale is 1)"),
_("the scale on Y axis"),
_("Scale"),
"res/actions/scale24_black.png")
.AddParameter("object", _("Object"))
.AddRequiredObjectCapabilityOnLastParameter("scalable")
.UseStandardParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Scale (1 by default)")))
.SetRequiredBaseObjectCapability("scalable")
.MarkAsAdvanced();
}
// Instruction for Flippable capability.
{
obj.AddAction("FlipX",
_("Flip the object horizontally"),
_("Flip the object horizontally"),
_("Flip horizontally _PARAM0_: _PARAM1_"),
_("Effects"),
"res/actions/flipX24.png",
"res/actions/flipX.png")
.AddParameter("object", _("Object"))
.AddRequiredObjectCapabilityOnLastParameter("flippable")
.AddParameter("yesorno", _("Activate flipping"))
.SetRequiredBaseObjectCapability("flippable")
.MarkAsSimple();
obj.AddAction("FlipY",
_("Flip the object vertically"),
_("Flip the object vertically"),
_("Flip vertically _PARAM0_: _PARAM1_"),
_("Effects"),
"res/actions/flipY24.png",
"res/actions/flipY.png")
.AddParameter("object", _("Object"))
.AddRequiredObjectCapabilityOnLastParameter("flippable")
.AddParameter("yesorno", _("Activate flipping"))
.SetRequiredBaseObjectCapability("flippable")
.MarkAsSimple();
obj.AddCondition("FlippedX",
_("Horizontally flipped"),
_("Check if the object is horizontally flipped"),
_("_PARAM0_ is horizontally flipped"),
_("Effects"),
"res/actions/flipX24.png",
"res/actions/flipX.png")
.AddParameter("object", _("Object"))
.AddRequiredObjectCapabilityOnLastParameter("flippable")
.SetRequiredBaseObjectCapability("flippable");
obj.AddCondition("FlippedY",
_("Vertically flipped"),
_("Check if the object is vertically flipped"),
_("_PARAM0_ is vertically flipped"),
_("Effects"),
"res/actions/flipY24.png",
"res/actions/flipY.png")
.AddParameter("object", _("Object"))
.AddRequiredObjectCapabilityOnLastParameter("flippable")
.SetRequiredBaseObjectCapability("flippable");
}
// Instruction for Animable capability.
{
obj.AddExpressionAndConditionAndAction(
"number", "AnimationIndex",
_("Animation (by number)"),
_("the number of the animation played by the object (the number from "
"the animations list)"),
_("the number of the animation"),
_("Animations and images"),
"res/actions/animation24.png")
.AddParameter("object", _("Object"))
.AddRequiredObjectCapabilityOnLastParameter("animable")
.UseStandardParameters("number", gd::ParameterOptions::MakeNewOptions())
.SetRequiredBaseObjectCapability("animable")
.MarkAsSimple();
obj.AddAction("SetAnimationName",
_("Animation (by name)"),
_("Change the animation played by the object, using the name of the "
"animation."),
_("Change the animation of _PARAM0_ to _PARAM1_"),
_("Animations and images"),
"res/actions/animation24.png",
"res/actions/animation.png")
.AddParameter("object", _("Object"))
.AddRequiredObjectCapabilityOnLastParameter("animable")
.AddParameter("objectAnimationName", _("Animation name"))
.SetRequiredBaseObjectCapability("animable")
.MarkAsAdvanced();
obj.AddCondition("AnimationName",
_("Animation (by name)"),
_("Check the animation played by the object."),
_("The animation of _PARAM0_ is _PARAM1_"),
_("Animations and images"),
"res/conditions/animation24.png",
"res/conditions/animation.png")
.AddParameter("object", _("Object"))
.AddRequiredObjectCapabilityOnLastParameter("animable")
.AddParameter("objectAnimationName", _("Animation name"))
.SetRequiredBaseObjectCapability("animable")
.MarkAsAdvanced();
obj.AddExpression("AnimationName",
_("Animation (by name)"),
_("the name of animation played by the object"),
_("Animations and images"),
"res/actions/animation.png")
.AddParameter("object", _("Object"))
.AddRequiredObjectCapabilityOnLastParameter("animable")
.SetRequiredBaseObjectCapability("animable");
obj.AddAction("PauseAnimation", _("Pause the animation"),
_("Pause the animation of the object"),
_("Pause the animation of _PARAM0_"),
_("Animations and images"),
"res/actions/animation24.png",
"res/actions/animation.png")
.AddParameter("object", _("Object"))
.AddRequiredObjectCapabilityOnLastParameter("animable")
.SetRequiredBaseObjectCapability("animable")
.MarkAsSimple();
obj.AddAction("PlayAnimation", _("Resume the animation"),
_("Resume the animation of the object"),
_("Resume the animation of _PARAM0_"),
_("Animations and images"),
"res/actions/animation24.png",
"res/actions/animation.png")
.AddParameter("object", _("Object"))
.AddRequiredObjectCapabilityOnLastParameter("animable")
.SetRequiredBaseObjectCapability("animable")
.MarkAsSimple();
obj.AddExpressionAndConditionAndAction(
"number", "AnimationSpeedScale",
_("Animation speed scale"),
_("the animation speed scale (1 = the default speed, >1 = faster and "
"<1 = slower)"),
_("the animation speed scale"),
_("Animations and images"),
"res/actions/animation24.png")
.AddParameter("object", _("Object"))
.AddRequiredObjectCapabilityOnLastParameter("animable")
.UseStandardParameters(
"number", gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Speed scale")))
.SetRequiredBaseObjectCapability("animable")
.MarkAsSimple();
obj.AddCondition("IsAnimationPaused",
_("Animation paused"),
_("Check if the animation of an object is paused."),
_("The animation of _PARAM0_ is paused"),
_("Animations and images"),
"res/conditions/animation24.png",
"res/conditions/animation.png")
.AddParameter("object", _("Object"))
.AddRequiredObjectCapabilityOnLastParameter("animable")
.SetRequiredBaseObjectCapability("animable")
.MarkAsSimple();
obj.AddCondition("HasAnimationEnded",
_("Animation finished"),
_("Check if the animation being played by the Sprite object "
"is finished."),
_("The animation of _PARAM0_ is finished"),
_("Animations and images"),
"res/conditions/animation24.png",
"res/conditions/animation.png")
.AddParameter("object", _("Object"))
.AddRequiredObjectCapabilityOnLastParameter("animable")
.SetRequiredBaseObjectCapability("animable")
.MarkAsSimple();
}
}
} // namespace gd

View File

@@ -110,11 +110,11 @@ void Direction::UnserializeFrom(const gd::SerializerElement& element) {
.GetBoolAttribute("automatic", true));
if (spriteElement.HasChild("CustomCollisionMask"))
sprite.SetCollisionMaskAutomatic(
sprite.SetFullImageCollisionMask(
!spriteElement.GetChild("CustomCollisionMask")
.GetBoolAttribute("custom", false));
else
sprite.SetCollisionMaskAutomatic(
sprite.SetFullImageCollisionMask(
!spriteElement.GetBoolAttribute("hasCustomCollisionMask", false));
std::vector<Polygon2d> mask;
@@ -173,7 +173,7 @@ void SaveSpritesDirection(const vector<Sprite>& sprites,
.SetAttribute("automatic", sprites[i].IsDefaultCenterPoint());
spriteElement.SetAttribute("hasCustomCollisionMask",
!sprites[i].IsCollisionMaskAutomatic());
!sprites[i].IsFullImageCollisionMask());
gd::SerializerElement& collisionMaskElement =
spriteElement.AddChild("customCollisionMask");

View File

@@ -4,7 +4,9 @@
* reserved. This project is released under the MIT License.
*/
#include "GDCore/Extensions/Builtin/SpriteExtension/Sprite.h"
#include <iostream>
#include "GDCore/Extensions/Builtin/SpriteExtension/Polygon2d.h"
using namespace std;
@@ -14,11 +16,10 @@ namespace gd {
Point Sprite::badPoint("");
Sprite::Sprite()
: automaticCollisionMask(true),
: fullImageCollisionMask(false),
origine("origine"),
centre("centre"),
automaticCentre(true) {
}
automaticCentre(true) {}
Sprite::~Sprite(){};

View File

@@ -7,6 +7,7 @@
#ifndef SPRITE_H
#define SPRITE_H
#include <memory>
#include "GDCore/Extensions/Builtin/SpriteExtension/Point.h"
#include "GDCore/Extensions/Builtin/SpriteExtension/Polygon2d.h"
#include "GDCore/String.h"
@@ -43,7 +44,7 @@ class GD_CORE_API Sprite {
/**
* \brief Get the collision mask (custom or automatically generated owing to
* IsCollisionMaskAutomatic())
* IsFullImageCollisionMask())
*
* \warning If the image has not been loaded ( using LoadImage ) and the
* collision mask is set as automatic, the returned mask won't be correct.
@@ -66,7 +67,7 @@ class GD_CORE_API Sprite {
/**
* \brief Set the custom collision mask.
* Call then `SetCollisionMaskAutomatic(false)` to use it.
* Call then `SetFullImageCollisionMask(false)` to use it.
*/
void SetCustomCollisionMask(const std::vector<Polygon2d>& collisionMask);
@@ -74,15 +75,15 @@ class GD_CORE_API Sprite {
* \brief Return true if the collision mask is a bounding box, false if a
* custom collision mask is used.
*/
inline bool IsCollisionMaskAutomatic() const {
return automaticCollisionMask;
inline bool IsFullImageCollisionMask() const {
return fullImageCollisionMask;
}
/**
* \brief Un/set use of the custom collision mask.
*/
inline void SetCollisionMaskAutomatic(bool enabled) {
automaticCollisionMask = enabled;
inline void SetFullImageCollisionMask(bool enabled) {
fullImageCollisionMask = enabled;
};
/**
@@ -161,9 +162,9 @@ class GD_CORE_API Sprite {
private:
gd::String image; ///< Name of the image to be loaded in Image Manager.
bool automaticCollisionMask; ///< True to use the custom collision mask.
///< Otherwise, a basic bounding box is returned
///< by GetCollisionMask()
bool fullImageCollisionMask; ///< True to use a bounding box wrapping the
///< whole image as collision mask. If false,
///< custom collision mask is used.
std::vector<Polygon2d> customCollisionMask; ///< Custom collision mask
std::vector<Point> points; ///< List of the points used by the sprite

View File

@@ -32,7 +32,11 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("Animated object which can be used for "
"most elements of a game"),
"CppPlatform/Extensions/spriteicon.png")
.SetCategoryFullName(_("General"));
.SetCategoryFullName(_("General"))
.MarkBaseObjectCapabilityAsSupported("resizable")
.MarkBaseObjectCapabilityAsSupported("scalable")
.MarkBaseObjectCapabilityAsSupported("flippable")
.MarkBaseObjectCapabilityAsSupported("animable");
obj.AddAction("Opacity",
_("Sprite opacity"),
@@ -50,6 +54,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("Opacity (0-255)")))
.MarkAsSimple();
// Deprecated
obj.AddAction("ChangeAnimation",
_("Change the animation"),
_("Change the animation of the object, using the animation "
@@ -62,8 +67,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
.AddParameter("object", _("Object"), "Sprite")
.UseStandardOperatorParameters("number",
ParameterOptions::MakeNewOptions())
.SetHidden()
.MarkAsSimple();
// Deprecated
obj.AddAction("SetAnimationName",
_("Change the animation (by name)"),
_("Change the animation of the object, using the name of the "
@@ -75,6 +82,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
.AddParameter("object", _("Object"), "Sprite")
.AddParameter("objectAnimationName", _("Animation name"))
.SetHidden()
.MarkAsAdvanced();
obj.AddAction(
@@ -107,6 +115,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
ParameterOptions::MakeNewOptions())
.MarkAsAdvanced();
// Deprecated
obj.AddAction("PauseAnimation",
_("Pause the animation"),
_("Pause the animation of the object"),
@@ -116,8 +125,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"res/actions/animation.png")
.AddParameter("object", _("Object"), "Sprite")
.SetHidden()
.MarkAsSimple();
// Deprecated
obj.AddAction("PlayAnimation",
_("Play the animation"),
_("Play the animation of the object"),
@@ -127,8 +138,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"res/actions/animation.png")
.AddParameter("object", _("Object"), "Sprite")
.SetHidden()
.MarkAsSimple();
// Deprecated
obj.AddAction(
"ChangeAnimationSpeedScale",
_("Animation speed scale"),
@@ -143,8 +156,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
.UseStandardOperatorParameters(
"number",
ParameterOptions::MakeNewOptions().SetDescription(_("Speed scale")))
.SetHidden()
.MarkAsSimple();
// Deprecated
obj.AddAction("TourneVersPos",
"Rotate an object toward a position",
"Rotate an object towards a position.",
@@ -159,8 +174,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
.AddParameter("expression", _("Angular speed (degrees per second)"))
.SetDefaultValue("0")
.AddCodeOnlyParameter("currentScene", "")
.SetHidden(); // Deprecated
.SetHidden();
// Deprecated
obj.AddAction("ChangeScale",
_("Scale"),
_("Modify the scale of the specified object."),
@@ -174,8 +190,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Scale (1 by default)")))
.MarkAsAdvanced();
.MarkAsAdvanced()
.SetHidden();
// Deprecated
obj.AddAction("ChangeScaleWidth",
_("Scale on X axis"),
_("Modify the scale of the width of an object."),
@@ -189,8 +207,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Scale (1 by default)")))
.MarkAsAdvanced();
.MarkAsAdvanced()
.SetHidden();
// Deprecated
obj.AddAction("ChangeScaleHeight",
_("Scale on Y axis"),
_("Modify the scale of the height of an object."),
@@ -204,8 +224,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Scale (1 by default)")))
.MarkAsAdvanced();
.MarkAsAdvanced()
.SetHidden();
// Deprecated
obj.AddAction("ChangeWidth",
_("Width"),
_("Change the width of a Sprite object."),
@@ -217,8 +239,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
.AddParameter("object", _("Object"), "Sprite")
.UseStandardOperatorParameters("number",
ParameterOptions::MakeNewOptions())
.MarkAsAdvanced();
.MarkAsAdvanced()
.SetHidden();
// Deprecated
obj.AddCondition("Width",
_("Width"),
_("Compare the width of a Sprite object."),
@@ -230,8 +254,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
.AddParameter("object", _("Object"), "Sprite")
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions())
.MarkAsAdvanced();
.MarkAsAdvanced()
.SetHidden();
// Deprecated
obj.AddAction("ChangeHeight",
_("Height"),
_("Change the height of a Sprite object."),
@@ -243,8 +269,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
.AddParameter("object", _("Object"), "Sprite")
.UseStandardOperatorParameters("number",
ParameterOptions::MakeNewOptions())
.MarkAsAdvanced();
.MarkAsAdvanced()
.SetHidden();
// Deprecated
obj.AddCondition("Height",
_("Height"),
_("Compare the height of a Sprite object."),
@@ -256,8 +284,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
.AddParameter("object", _("Object"), "Sprite")
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions())
.MarkAsAdvanced();
.MarkAsAdvanced()
.SetHidden();
// Deprecated
obj.AddAction("SetSize",
_("Size"),
_("Change the size of an object."),
@@ -269,8 +299,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
.AddParameter("object", _("Object"))
.AddParameter("expression", _("Width"))
.AddParameter("expression", _("Height"))
.MarkAsAdvanced();
.MarkAsAdvanced()
.SetHidden();
// Deprecated
obj.AddCondition(
"Animation",
_("Current animation"),
@@ -283,8 +315,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
.AddParameter("object", _("Object"), "Sprite")
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions())
.SetHidden()
.MarkAsAdvanced();
// Deprecated
obj.AddCondition("AnimationName",
_("Current animation name"),
_("Check the animation played by the object."),
@@ -295,6 +329,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
.AddParameter("object", _("Object"), "Sprite")
.AddParameter("objectAnimationName", _("Animation name"))
.SetHidden()
.MarkAsAdvanced();
obj.AddCondition(
@@ -328,6 +363,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"number", ParameterOptions::MakeNewOptions())
.MarkAsAdvanced();
// Deprecated
obj.AddCondition("AnimStopped",
_("Animation paused"),
_("Check if the animation of an object is paused."),
@@ -337,8 +373,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"res/conditions/animation.png")
.AddParameter("object", _("Object"), "Sprite")
.SetHidden()
.MarkAsSimple();
// Deprecated
obj.AddCondition("AnimationEnded",
_("Animation finished"),
_("Check if the animation being played by the Sprite object "
@@ -352,6 +390,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
.MarkAsSimple()
.SetHidden();
// Deprecated
obj.AddCondition("AnimationEnded2",
_("Animation finished"),
_("Check if the animation being played by the Sprite object "
@@ -362,6 +401,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"res/conditions/animation.png")
.AddParameter("object", _("Object"), "Sprite")
.SetHidden()
.MarkAsSimple();
obj.AddCondition("ScaleWidth",
@@ -456,9 +496,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("Effects"),
"res/actions/flipX24.png",
"res/actions/flipX.png")
.AddParameter("object", _("Object"), "Sprite")
.AddParameter("yesorno", _("Activate flipping"))
.SetHidden()
.MarkAsSimple();
obj.AddAction("FlipY",
@@ -468,9 +508,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("Effects"),
"res/actions/flipY24.png",
"res/actions/flipY.png")
.AddParameter("object", _("Object"), "Sprite")
.AddParameter("yesorno", _("Activate flipping"))
.SetHidden()
.MarkAsSimple();
obj.AddCondition("FlippedX",
@@ -480,8 +520,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("Effects"),
"res/actions/flipX24.png",
"res/actions/flipX.png")
.AddParameter("object", _("Object"), "Sprite");
.AddParameter("object", _("Object"), "Sprite")
.SetHidden();
obj.AddCondition("FlippedY",
_("Vertically flipped"),
@@ -490,9 +530,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("Effects"),
"res/actions/flipY24.png",
"res/actions/flipY.png")
.AddParameter("object", _("Object"), "Sprite")
.SetHidden();
.AddParameter("object", _("Object"), "Sprite");
// Deprecated
obj.AddAction("TourneVers",
"Rotate an object toward another",
"Rotate an object towards another.",
@@ -504,7 +545,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
.AddParameter("object", _("Object"), "Sprite")
.AddParameter("objectPtr", "Rotate toward this object")
.AddCodeOnlyParameter("currentScene", "")
.SetHidden(); // Deprecated
.SetHidden();
obj.AddExpression("X",
_("X position of a point"),
@@ -542,6 +583,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
.AddParameter("object", _("Object"), "Sprite")
.AddParameter("objectPointName", _("Name of the point"));
// Deprecated
obj.AddExpression("Direc",
_("Direction"),
_("Direction of the object"),
@@ -550,6 +592,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
.SetHidden()
.AddParameter("object", _("Object"), "Sprite");
// Deprecated
obj.AddExpression("Direction",
_("Direction"),
_("Direction of the object"),
@@ -559,6 +602,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
// interface.
.AddParameter("object", _("Object"), "Sprite");
// Deprecated
obj.AddExpression("Anim",
_("Animation"),
_("Animation of the object"),
@@ -567,20 +611,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
.SetHidden()
.AddParameter("object", _("Object"), "Sprite");
obj.AddExpression("Animation",
_("Animation"),
_("Animation of the object"),
_("Animations and images"),
"res/actions/animation.png")
.AddParameter("object", _("Object"), "Sprite");
obj.AddStrExpression("AnimationName",
_("Animation name"),
_("Name of the animation of the object"),
_("Animations and images"),
"res/actions/animation.png")
.AddParameter("object", _("Object"), "Sprite");
obj.AddExpression("Sprite",
_("Image"),
_("Current frame of the animation of the object"),
@@ -595,27 +625,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"res/actions/sprite.png")
.AddParameter("object", _("Object"), "Sprite");
obj.AddExpression("AnimationSpeedScale",
_("Animation speed scale"),
_("Animation speed scale"),
_("Animations and images"),
"res/actions/animation.png")
.AddParameter("object", _("Object"), "Sprite");
obj.AddExpression("ScaleX",
_("Scale of the width of an object"),
_("Scale of the width of an object"),
_("Size"),
"res/actions/scaleWidth_black.png")
.AddParameter("object", _("Object"), "Sprite");
obj.AddExpression("ScaleY",
_("Scale of the height of an object"),
_("Scale of the height of an object"),
_("Size"),
"res/actions/scaleHeight_black.png")
.AddParameter("object", _("Object"), "Sprite");
obj.AddExpression("Opacity",
_("Opacity"),
_("Opacity"),

View File

@@ -25,13 +25,16 @@ namespace gd {
Animation SpriteObject::badAnimation;
SpriteObject::SpriteObject() : updateIfNotVisible(false) {}
SpriteObject::SpriteObject()
: updateIfNotVisible(false), adaptCollisionMaskAutomatically(true) {}
SpriteObject::~SpriteObject(){};
void SpriteObject::DoUnserializeFrom(gd::Project& project,
const gd::SerializerElement& element) {
updateIfNotVisible = element.GetBoolAttribute("updateIfNotVisible", true);
adaptCollisionMaskAutomatically =
element.GetBoolAttribute("adaptCollisionMaskAutomatically", false);
RemoveAllAnimations();
const gd::SerializerElement& animationsElement =
@@ -80,6 +83,8 @@ void SpriteObject::DoUnserializeFrom(gd::Project& project,
void SpriteObject::DoSerializeTo(gd::SerializerElement& element) const {
element.SetAttribute("updateIfNotVisible", updateIfNotVisible);
element.SetAttribute("adaptCollisionMaskAutomatically",
adaptCollisionMaskAutomatically);
// Animations
gd::SerializerElement& animationsElement = element.AddChild("animations");

View File

@@ -47,8 +47,7 @@ class GD_CORE_API SpriteObject : public gd::ObjectConfiguration {
void ExposeResources(gd::ArbitraryResourceWorker& worker) override;
std::map<gd::String, gd::PropertyDescriptor> GetProperties() const override;
bool UpdateProperty(const gd::String& name,
const gd::String& value) override;
bool UpdateProperty(const gd::String& name, const gd::String& value) override;
std::map<gd::String, gd::PropertyDescriptor> GetInitialInstanceProperties(
const gd::InitialInstance& position,
@@ -118,14 +117,30 @@ class GD_CORE_API SpriteObject : public gd::ObjectConfiguration {
const std::vector<Animation>& GetAllAnimations() const { return animations; }
/**
* \brief Set if the object animation should be played even if the object is hidden
* or far from the camera.
* @brief Check if the collision mask adapts automatically to the animation.
*/
void SetUpdateIfNotVisible(bool updateIfNotVisible_) { updateIfNotVisible = updateIfNotVisible_; }
bool AdaptCollisionMaskAutomatically() const {
return adaptCollisionMaskAutomatically;
}
/**
* \brief Check if the object animation should be played even if the object is hidden
* or far from the camera (false by default).
* @brief Set if the collision mask adapts automatically to the animation.
*/
void SetAdaptCollisionMaskAutomatically(bool enable) {
adaptCollisionMaskAutomatically = enable;
}
/**
* \brief Set if the object animation should be played even if the object is
* hidden or far from the camera.
*/
void SetUpdateIfNotVisible(bool updateIfNotVisible_) {
updateIfNotVisible = updateIfNotVisible_;
}
/**
* \brief Check if the object animation should be played even if the object
* is hidden or far from the camera (false by default).
*/
bool GetUpdateIfNotVisible() const { return updateIfNotVisible; }
///@}
@@ -137,11 +152,15 @@ class GD_CORE_API SpriteObject : public gd::ObjectConfiguration {
mutable std::vector<Animation> animations;
bool updateIfNotVisible; ///< If set to true, ask the game engine to play
///< object animation even if hidden or far from the
///< screen.
///< object animation even if hidden or far from
///< the screen.
static Animation badAnimation; //< Bad animation when an out of bound
// animation is requested.
static Animation badAnimation; //< Bad animation when an out of bound
// animation is requested.
bool adaptCollisionMaskAutomatically; ///< If set to true, the collision
///< mask will be automatically
///< adapted to the animation of the
///< object.
};
} // namespace gd

View File

@@ -0,0 +1,140 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#pragma once
#include <algorithm>
#include <functional>
#include <map>
#include <memory>
#include "GDCore/Events/Instruction.h"
#include "GDCore/String.h"
namespace gd {
class Project;
class Layout;
class EventsCodeGenerator;
class EventsCodeGenerationContext;
class SerializerElement;
class ObjectType;
} // namespace gd
namespace gd {
/**
* \brief Describe user-friendly information about an expression or an
* instruction (action or condition), its parameters and the function name as
* well as other information for code generation.
*
* \ingroup Events
*/
class GD_CORE_API AbstractFunctionMetadata {
public:
AbstractFunctionMetadata(){};
virtual ~AbstractFunctionMetadata(){};
/**
* \see gd::InstructionMetadata::AddParameter
*/
virtual AbstractFunctionMetadata &
AddParameter(const gd::String &type, const gd::String &label,
const gd::String &supplementaryInformation = "",
bool parameterIsOptional = false) = 0;
/**
* \see gd::InstructionMetadata::AddCodeOnlyParameter
*/
virtual AbstractFunctionMetadata &
AddCodeOnlyParameter(const gd::String &type,
const gd::String &supplementaryInformation) = 0;
/**
* \see gd::InstructionMetadata::SetDefaultValue
*/
virtual AbstractFunctionMetadata &
SetDefaultValue(const gd::String &defaultValue) = 0;
/**
* \see gd::InstructionMetadata::SetParameterExtraInfo
*/
virtual AbstractFunctionMetadata &
SetParameterExtraInfo(const gd::String &extraInfo) = 0;
/**
* \see gd::InstructionMetadata::SetParameterObjectType
*/
virtual AbstractFunctionMetadata &
SetParameterObjectType(const gd::ObjectType &objectType) = 0;
/**
* \see gd::InstructionMetadata::SetParameterLongDescription
*/
virtual AbstractFunctionMetadata &
SetParameterLongDescription(const gd::String &longDescription) = 0;
/**
* \see gd::InstructionMetadata::SetHidden
*/
virtual AbstractFunctionMetadata &SetHidden() = 0;
/**
* Set that the instruction is private - it can't be used outside of the
* object/ behavior that it is attached too.
*/
virtual AbstractFunctionMetadata &SetPrivate() = 0;
/**
* Set that the instruction can be used in layouts or external events.
*/
virtual AbstractFunctionMetadata &SetRelevantForLayoutEventsOnly() = 0;
/**
* Set that the instruction can be used in function events.
*/
virtual AbstractFunctionMetadata &SetRelevantForFunctionEventsOnly() = 0;
/**
* Set that the instruction can be used in asynchronous function events.
*/
virtual AbstractFunctionMetadata &
SetRelevantForAsynchronousFunctionEventsOnly() = 0;
/**
* Set that the instruction can be used in custom object events.
*/
virtual AbstractFunctionMetadata &SetRelevantForCustomObjectEventsOnly() = 0;
/**
* \brief Set the function that should be called when generating the source
* code from events.
* \param functionName the name of the function to call
* \note Shortcut for `codeExtraInformation.SetFunctionName`.
*/
virtual AbstractFunctionMetadata &
SetFunctionName(const gd::String &functionName) = 0;
/**
* \brief Erase any existing include file and add the specified include.
*/
virtual AbstractFunctionMetadata &
SetIncludeFile(const gd::String &includeFile) = 0;
/**
* \brief Add a file to the already existing include files.
*/
virtual AbstractFunctionMetadata &
AddIncludeFile(const gd::String &includeFile) = 0;
/**
* \brief Get the files that must be included to use the instruction.
*/
virtual const std::vector<gd::String> &GetIncludeFiles() const = 0;
private:
};
} // namespace gd

View File

@@ -3,13 +3,17 @@
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#ifndef BEHAVIORMETADATA_H
#define BEHAVIORMETADATA_H
#pragma once
#include "InstructionOrExpressionContainerMetadata.h"
#include <map>
#include "GDCore/Extensions/Metadata/ExpressionMetadata.h"
#include "GDCore/Extensions/Metadata/InstructionMetadata.h"
#include "GDCore/Project/ObjectType.h"
#include "GDCore/String.h"
namespace gd {
class Behavior;
class BehaviorsSharedData;
@@ -25,7 +29,7 @@ namespace gd {
*
* \ingroup Events
*/
class GD_CORE_API BehaviorMetadata {
class GD_CORE_API BehaviorMetadata : public InstructionOrExpressionContainerMetadata {
public:
BehaviorMetadata(
const gd::String& extensionNamespace,
@@ -67,7 +71,7 @@ class GD_CORE_API BehaviorMetadata {
const gd::String& sentence_,
const gd::String& group_,
const gd::String& icon_,
const gd::String& smallicon_);
const gd::String& smallicon_) override;
/**
* Declare a new action as being part of the behavior.
@@ -80,7 +84,7 @@ class GD_CORE_API BehaviorMetadata {
const gd::String& sentence_,
const gd::String& group_,
const gd::String& icon_,
const gd::String& smallicon_);
const gd::String& smallicon_) override;
/**
* Declare a new condition as being part of the behavior.
@@ -91,7 +95,7 @@ class GD_CORE_API BehaviorMetadata {
const gd::String& sentence_,
const gd::String& group_,
const gd::String& icon_,
const gd::String& smallicon_);
const gd::String& smallicon_) override;
/**
* Declare a new action as being part of the behavior.
@@ -102,7 +106,7 @@ class GD_CORE_API BehaviorMetadata {
const gd::String& sentence_,
const gd::String& group_,
const gd::String& icon_,
const gd::String& smallicon_);
const gd::String& smallicon_) override;
/**
* Declare a new action as being part of the extension.
*/
@@ -110,7 +114,7 @@ class GD_CORE_API BehaviorMetadata {
const gd::String& fullname_,
const gd::String& description_,
const gd::String& group_,
const gd::String& smallicon_);
const gd::String& smallicon_) override;
/**
* Declare a new string expression as being part of the extension.
@@ -119,7 +123,7 @@ class GD_CORE_API BehaviorMetadata {
const gd::String& fullname_,
const gd::String& description_,
const gd::String& group_,
const gd::String& smallicon_);
const gd::String& smallicon_) override;
/**
* \brief Declare a new expression and condition as being part of the
@@ -134,7 +138,7 @@ class GD_CORE_API BehaviorMetadata {
const gd::String& description,
const gd::String& sentenceName,
const gd::String& group,
const gd::String& icon);
const gd::String& icon) override;
/**
* \brief Declare a new expression, condition and action as being part of the
@@ -151,7 +155,7 @@ class GD_CORE_API BehaviorMetadata {
const gd::String& description,
const gd::String& sentenceName,
const gd::String& group,
const gd::String& icon);
const gd::String& icon) override;
/**
* \brief Create a new action which is the duplicate of the specified one.
@@ -160,7 +164,7 @@ class GD_CORE_API BehaviorMetadata {
* one.
*/
gd::InstructionMetadata& AddDuplicatedAction(
const gd::String& newActionName, const gd::String& copiedActionName);
const gd::String& newActionName, const gd::String& copiedActionName) override;
/**
* \brief Create a new condition which is the duplicate of the specified one.
@@ -170,7 +174,7 @@ class GD_CORE_API BehaviorMetadata {
*/
gd::InstructionMetadata& AddDuplicatedCondition(
const gd::String& newConditionName,
const gd::String& copiedConditionName);
const gd::String& copiedConditionName) override;
/**
* \brief Create a new expression which is the duplicate of the specified one.
@@ -193,9 +197,9 @@ class GD_CORE_API BehaviorMetadata {
const gd::String& newExpressionName,
const gd::String& copiedExpressionName);
BehaviorMetadata& SetFullName(const gd::String& fullname_);
BehaviorMetadata& SetFullName(const gd::String& fullname_) override;
BehaviorMetadata& SetDefaultName(const gd::String& defaultName_);
BehaviorMetadata& SetDescription(const gd::String& description_);
BehaviorMetadata& SetDescription(const gd::String& description_) override;
BehaviorMetadata& SetGroup(const gd::String& group_);
/**
@@ -203,12 +207,12 @@ class GD_CORE_API BehaviorMetadata {
* \note The requirement may vary depending on the platform: Most of the time,
* the include file contains the declaration of the behavior.
*/
BehaviorMetadata& SetIncludeFile(const gd::String& includeFile);
BehaviorMetadata& SetIncludeFile(const gd::String& includeFile) override;
/**
* \brief Add a file to the already existing include files.
*/
BehaviorMetadata& AddIncludeFile(const gd::String& includeFile);
BehaviorMetadata& AddIncludeFile(const gd::String& includeFile) override;
/**
* \brief Add a file to the already existing required files.
@@ -221,7 +225,7 @@ class GD_CORE_API BehaviorMetadata {
* Get the help path of the behavior, relative to the GDevelop documentation
* root.
*/
const gd::String& GetHelpPath() const { return helpPath; }
const gd::String& GetHelpPath() const override { return helpPath; }
/**
* Set the help path of the behavior, relative to the GDevelop documentation
@@ -230,22 +234,22 @@ class GD_CORE_API BehaviorMetadata {
* The behavior instructions will have this help path set by
* default, unless you call SetHelpPath on them.
*/
BehaviorMetadata& SetHelpPath(const gd::String& path) {
BehaviorMetadata& SetHelpPath(const gd::String& path) override {
helpPath = path;
return *this;
}
const gd::String& GetName() const;
const gd::String& GetFullName() const { return fullname; }
const gd::String& GetName() const override;
const gd::String& GetFullName() const override { return fullname; }
const gd::String& GetDefaultName() const { return defaultName; }
const gd::String& GetDescription() const { return description; }
const gd::String& GetDescription() const override { return description; }
const gd::String& GetGroup() const { return group; }
const gd::String& GetIconFilename() const { return iconFilename; }
const gd::String& GetIconFilename() const override { return iconFilename; }
/**
* \brief Set the type of the object that this behavior can be used on.
*/
BehaviorMetadata& SetObjectType(const gd::String& objectType_) {
BehaviorMetadata& SetObjectType(const gd::ObjectType& objectType_) {
objectType = objectType_;
return *this;
}
@@ -255,7 +259,7 @@ class GD_CORE_API BehaviorMetadata {
*
* \note An empty string means the base object, so any object.
*/
const gd::String& GetObjectType() const { return objectType; }
const gd::ObjectType& GetObjectType() const { return objectType; }
/**
* Check if the behavior is private - it can't be used outside of its
@@ -293,22 +297,22 @@ class GD_CORE_API BehaviorMetadata {
* \brief Return a reference to a map containing the names of the actions
* (as keys) and the metadata associated with (as values).
*/
std::map<gd::String, gd::InstructionMetadata>& GetAllActions() { return actionsInfos; };
std::map<gd::String, gd::InstructionMetadata>& GetAllActions() override { return actionsInfos; };
/**
* \see gd::PlatformExtension::GetAllActions
*/
std::map<gd::String, gd::InstructionMetadata>& GetAllConditions() { return conditionsInfos; };
std::map<gd::String, gd::InstructionMetadata>& GetAllConditions() override { return conditionsInfos; };
/**
* \see gd::PlatformExtension::GetAllActions
*/
std::map<gd::String, gd::ExpressionMetadata>& GetAllExpressions() { return expressionsInfos; };
std::map<gd::String, gd::ExpressionMetadata>& GetAllExpressions() override { return expressionsInfos; };
/**
* \see gd::PlatformExtension::GetAllActions
*/
std::map<gd::String, gd::ExpressionMetadata>& GetAllStrExpressions() { return strExpressionsInfos; };
std::map<gd::String, gd::ExpressionMetadata>& GetAllStrExpressions() override { return strExpressionsInfos; };
std::map<gd::String, gd::InstructionMetadata> conditionsInfos;
std::map<gd::String, gd::InstructionMetadata> actionsInfos;
@@ -327,7 +331,7 @@ class GD_CORE_API BehaviorMetadata {
gd::String description;
gd::String group;
gd::String iconFilename;
gd::String objectType;
gd::ObjectType objectType;
bool isPrivate = false;
// TODO: Nitpicking: convert these to std::unique_ptr to clarify ownership.
@@ -337,5 +341,3 @@ class GD_CORE_API BehaviorMetadata {
};
} // namespace gd
#endif // BEHAVIORMETADATA_H

View File

@@ -42,21 +42,25 @@ gd::ExpressionMetadata& ExpressionMetadata::AddParameter(
info.description = description;
info.codeOnly = false;
info.SetOptional(parameterIsOptional);
info.SetExtraInfo(
gd::String fixedSupplementaryInformation =
// For objects/behavior, the supplementary information
// parameter is an object/behavior type...
((gd::ParameterMetadata::IsObject(type) ||
gd::ParameterMetadata::IsBehavior(type))
gd::ParameterMetadata::IsBehavior(type))
// Prefix with the namespace if it's not already there.
&& !(supplementaryInformation.rfind(extensionNamespace, 0) == 0))
? (supplementaryInformation.empty()
? ""
: extensionNamespace +
supplementaryInformation //... so prefix it with the extension
// namespace.
)
: supplementaryInformation); // Otherwise don't change anything
//... so prefix it with the extension namespace.
: extensionNamespace + supplementaryInformation)
// Otherwise don't change anything
: supplementaryInformation;
if (gd::ParameterMetadata::IsObject(type)) {
info.GetValueTypeMetadata().GetObjectType().SetName(fixedSupplementaryInformation);
} else {
info.SetExtraInfo(fixedSupplementaryInformation);
}
// TODO: Assert against supplementaryInformation === "emsc" (when running with
// Emscripten), and warn about a missing argument when calling addParameter.
@@ -75,8 +79,7 @@ gd::ExpressionMetadata& ExpressionMetadata::AddCodeOnlyParameter(
return *this;
}
gd::ExpressionMetadata& ExpressionMetadata::SetRequiresBaseObjectCapability(
gd::ExpressionMetadata& ExpressionMetadata::SetRequiredBaseObjectCapability(
const gd::String& capability) {
requiredBaseObjectCapability = capability;
return *this;

View File

@@ -3,9 +3,10 @@
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#ifndef EXPRESSIONMETADATA_H
#define EXPRESSIONMETADATA_H
#if defined(GD_IDE_ONLY)
#pragma once
#include "AbstractFunctionMetadata.h"
#include <functional>
#include <memory>
@@ -17,7 +18,6 @@ class Layout;
}
namespace gd {
/**
* \brief Information about how generate code for an expression
*/
@@ -27,79 +27,7 @@ class ExpressionCodeGenerationInformation {
: staticFunction(false), hasCustomCodeGenerator(false){};
virtual ~ExpressionCodeGenerationInformation(){};
/**
* \brief Set the function name which will be used when generating the code.
* \param functionName the name of the function to call
*/
ExpressionCodeGenerationInformation& SetFunctionName(
const gd::String& functionName) {
functionCallName = functionName;
return *this;
}
/**
* \brief Set that the function is static
*/
ExpressionCodeGenerationInformation& SetStatic() {
staticFunction = true;
return *this;
}
/**
* \brief Erase any existing include file and add the specified include.
*/
ExpressionCodeGenerationInformation& SetIncludeFile(
const gd::String& includeFile) {
includeFiles.clear();
includeFiles.push_back(includeFile);
return *this;
}
/**
* \brief Add a file to the already existing include files.
*/
ExpressionCodeGenerationInformation& AddIncludeFile(
const gd::String& includeFile) {
if (std::find(includeFiles.begin(), includeFiles.end(), includeFile) ==
includeFiles.end())
includeFiles.push_back(includeFile);
return *this;
}
/**
* \brief Get the files that must be included to use the instruction.
*/
const std::vector<gd::String>& GetIncludeFiles() const {
return includeFiles;
};
/**
* \brief Set that the function must be generated using a custom code
* generator.
*/
ExpressionCodeGenerationInformation& SetCustomCodeGenerator(
std::function<gd::String(const std::vector<gd::Expression>& parameters,
gd::EventsCodeGenerator& codeGenerator,
gd::EventsCodeGenerationContext& context)>
codeGenerator) {
hasCustomCodeGenerator = true;
customCodeGenerator = codeGenerator;
return *this;
}
ExpressionCodeGenerationInformation& RemoveCustomCodeGenerator() {
hasCustomCodeGenerator = false;
std::function<gd::String(const std::vector<gd::Expression>& parameters,
gd::EventsCodeGenerator& codeGenerator,
gd::EventsCodeGenerationContext& context)>
emptyFunction;
customCodeGenerator = emptyFunction;
return *this;
}
bool HasCustomCodeGenerator() const { return hasCustomCodeGenerator; }
// TODO Move these attributes to ExpressionMetadata.
bool staticFunction;
gd::String functionCallName;
bool hasCustomCodeGenerator;
@@ -107,8 +35,6 @@ class ExpressionCodeGenerationInformation {
gd::EventsCodeGenerator& codeGenerator,
gd::EventsCodeGenerationContext& context)>
customCodeGenerator;
private:
std::vector<gd::String> includeFiles;
};
@@ -118,7 +44,7 @@ class ExpressionCodeGenerationInformation {
*
* \ingroup Events
*/
class GD_CORE_API ExpressionMetadata {
class GD_CORE_API ExpressionMetadata : public gd::AbstractFunctionMetadata {
public:
/**
* Construct a new expression metadata.
@@ -144,7 +70,7 @@ class GD_CORE_API ExpressionMetadata {
/**
* \brief Set the expression as not shown in the IDE.
*/
ExpressionMetadata& SetHidden();
ExpressionMetadata& SetHidden() override;
/**
* \brief Set the group of the instruction in the IDE.
@@ -179,7 +105,7 @@ class GD_CORE_API ExpressionMetadata {
* Set that the instruction is private - it can't be used outside of the
* object/ behavior that it is attached too.
*/
ExpressionMetadata& SetPrivate() {
ExpressionMetadata& SetPrivate() override {
isPrivate = true;
return *this;
}
@@ -216,7 +142,7 @@ class GD_CORE_API ExpressionMetadata {
/**
* Set that the instruction can be used in layouts or external events.
*/
ExpressionMetadata &SetRelevantForLayoutEventsOnly() {
ExpressionMetadata &SetRelevantForLayoutEventsOnly() override {
relevantContext = "Layout";
return *this;
}
@@ -224,7 +150,7 @@ class GD_CORE_API ExpressionMetadata {
/**
* Set that the instruction can be used in function events.
*/
ExpressionMetadata &SetRelevantForFunctionEventsOnly() {
ExpressionMetadata &SetRelevantForFunctionEventsOnly() override {
relevantContext = "Function";
return *this;
}
@@ -232,7 +158,7 @@ class GD_CORE_API ExpressionMetadata {
/**
* Set that the instruction can be used in asynchronous function events.
*/
ExpressionMetadata &SetRelevantForAsynchronousFunctionEventsOnly() {
ExpressionMetadata &SetRelevantForAsynchronousFunctionEventsOnly() override {
relevantContext = "AsynchronousFunction";
return *this;
}
@@ -240,7 +166,7 @@ class GD_CORE_API ExpressionMetadata {
/**
* Set that the instruction can be used in custom object events.
*/
ExpressionMetadata &SetRelevantForCustomObjectEventsOnly() {
ExpressionMetadata &SetRelevantForCustomObjectEventsOnly() override {
relevantContext = "Object";
return *this;
}
@@ -248,17 +174,17 @@ class GD_CORE_API ExpressionMetadata {
/**
* \see gd::InstructionMetadata::AddParameter
*/
gd::ExpressionMetadata& AddParameter(
const gd::String& type,
const gd::String& description,
const gd::String& supplementaryInformation = "",
bool parameterIsOptional = false);
gd::ExpressionMetadata &
AddParameter(const gd::String &type, const gd::String &label,
const gd::String &supplementaryInformation = "",
bool parameterIsOptional = false) override;
/**
* \see gd::InstructionMetadata::AddCodeOnlyParameter
*/
gd::ExpressionMetadata& AddCodeOnlyParameter(
const gd::String& type, const gd::String& supplementaryInformation);
gd::ExpressionMetadata &
AddCodeOnlyParameter(const gd::String &type,
const gd::String &supplementaryInformation) override;
/**
* Set the default value used in editor (or if an optional parameter is empty
@@ -266,8 +192,9 @@ class GD_CORE_API ExpressionMetadata {
*
* \see AddParameter
*/
ExpressionMetadata& SetDefaultValue(gd::String defaultValue_) {
if (!parameters.empty()) parameters.back().SetDefaultValue(defaultValue_);
ExpressionMetadata &SetDefaultValue(const gd::String &defaultValue) override {
if (!parameters.empty())
parameters.back().SetDefaultValue(defaultValue);
return *this;
};
@@ -277,7 +204,8 @@ class GD_CORE_API ExpressionMetadata {
*
* \see AddParameter
*/
ExpressionMetadata& SetParameterLongDescription(gd::String longDescription) {
ExpressionMetadata &
SetParameterLongDescription(const gd::String &longDescription) override {
if (!parameters.empty())
parameters.back().SetLongDescription(longDescription);
return *this;
@@ -290,18 +218,47 @@ class GD_CORE_API ExpressionMetadata {
*
* \see AddParameter
*/
ExpressionMetadata &SetParameterExtraInfo(const gd::String &extraInfo) {
ExpressionMetadata &SetParameterExtraInfo(
const gd::String &extraInfo) override {
if (!parameters.empty()) parameters.back().SetExtraInfo(extraInfo);
return *this;
}
/**
* \brief Set the type of object accepted by the last parameter (only apply
* for object parameter).
*
* \see AddParameter
*/
ExpressionMetadata &
SetParameterObjectType(const gd::ObjectType &objectType) override {
if (!parameters.empty()) {
parameters.back().GetValueTypeMetadata().SetObjectType(objectType);
}
return *this;
}
/**
* \brief Set the capabilities of the objects accepted by the last parameter
* (only apply for object parameter).
*
* \see AddParameter
*/
ExpressionMetadata &
AddRequiredObjectCapabilityOnLastParameter(const gd::String &capability) {
if (!parameters.empty()) {
parameters.back().GetValueTypeMetadata().GetObjectType().AddCapability(capability);
}
return *this;
}
/**
* \brief Mark this (object) expression as requiring the specified capability,
* offered by the base object.
* This is useful for some objects that don't support this capability, so that
* the editor can hide the expression as it does not apply to them.
*/
ExpressionMetadata& SetRequiresBaseObjectCapability(
ExpressionMetadata& SetRequiredBaseObjectCapability(
const gd::String& capability);
/**
@@ -312,50 +269,6 @@ class GD_CORE_API ExpressionMetadata {
return requiredBaseObjectCapability;
};
/**
* \brief Set the function that should be called when generating the source
* code from events.
* \param functionName the name of the function to call
* \note Shortcut for `codeExtraInformation.SetFunctionName`.
*/
ExpressionCodeGenerationInformation& SetFunctionName(
const gd::String& functionName) {
return codeExtraInformation.SetFunctionName(functionName);
}
/**
* \brief Return the structure containing the information about code
* generation for the expression.
*/
ExpressionCodeGenerationInformation& GetCodeExtraInformation() {
return codeExtraInformation;
}
/**
* \brief Erase any existing include file and add the specified include.
*/
ExpressionMetadata &SetIncludeFile(const gd::String &includeFile) {
codeExtraInformation.SetIncludeFile(includeFile);
return *this;
}
/**
* \brief Add a file to the already existing include files.
*/
ExpressionMetadata &AddIncludeFile(const gd::String &includeFile) {
codeExtraInformation.AddIncludeFile(includeFile);
return *this;
}
/**
* \brief Get the files that must be included to use the instruction.
*/
const std::vector<gd::String>& GetIncludeFiles() const {
return codeExtraInformation.GetIncludeFiles();
}
ExpressionCodeGenerationInformation codeExtraInformation;
bool IsShown() const { return shown; }
const gd::String& GetReturnType() const { return returnType; }
const gd::String& GetFullName() const { return fullname; }
@@ -375,6 +288,99 @@ class GD_CORE_API ExpressionMetadata {
std::vector<gd::ParameterMetadata> parameters;
/**
* \brief Set the function name which will be used when generating the code.
* \param functionName the name of the function to call
*/
ExpressionMetadata& SetFunctionName(
const gd::String& functionName) override {
codeExtraInformation.functionCallName = functionName;
return *this;
}
/**
* \brief Return the name of the function which will be called in the generated code.
*/
const gd::String &GetFunctionName() {
return codeExtraInformation.functionCallName;
}
/**
* \brief Set that the function is static
*/
ExpressionMetadata& SetStatic() {
codeExtraInformation.staticFunction = true;
return *this;
}
/**
* \brief Erase any existing include file and add the specified include.
*/
ExpressionMetadata& SetIncludeFile(
const gd::String& includeFile) override {
codeExtraInformation.includeFiles.clear();
codeExtraInformation.includeFiles.push_back(includeFile);
return *this;
}
/**
* \brief Add a file to the already existing include files.
*/
ExpressionMetadata& AddIncludeFile(
const gd::String& includeFile) override {
if (std::find(codeExtraInformation.includeFiles.begin(), codeExtraInformation.includeFiles.end(), includeFile) ==
codeExtraInformation.includeFiles.end())
codeExtraInformation.includeFiles.push_back(includeFile);
return *this;
}
/**
* \brief Get the files that must be included to use the instruction.
*/
const std::vector<gd::String>& GetIncludeFiles() const override {
return codeExtraInformation.includeFiles;
};
/**
* \brief Set that the function must be generated using a custom code
* generator.
*/
ExpressionMetadata& SetCustomCodeGenerator(
std::function<gd::String(const std::vector<gd::Expression>& parameters,
gd::EventsCodeGenerator& codeGenerator,
gd::EventsCodeGenerationContext& context)>
codeGenerator) {
codeExtraInformation.hasCustomCodeGenerator = true;
codeExtraInformation.customCodeGenerator = codeGenerator;
return *this;
}
ExpressionMetadata& RemoveCustomCodeGenerator() {
codeExtraInformation.hasCustomCodeGenerator = false;
std::function<gd::String(const std::vector<gd::Expression>& parameters,
gd::EventsCodeGenerator& codeGenerator,
gd::EventsCodeGenerationContext& context)>
emptyFunction;
codeExtraInformation.customCodeGenerator = emptyFunction;
return *this;
}
bool HasCustomCodeGenerator() const { return codeExtraInformation.hasCustomCodeGenerator; }
/**
* \brief Return the structure containing the information about code
* generation for the expression.
*
* \deprecated
*/
ExpressionMetadata& GetCodeExtraInformation() {
return *this;
}
ExpressionCodeGenerationInformation codeExtraInformation;
private:
gd::String returnType;
gd::String fullname;
@@ -391,6 +397,3 @@ class GD_CORE_API ExpressionMetadata {
};
} // namespace gd
#endif
#endif // EXPRESSIONMETADATA_H

View File

@@ -11,7 +11,7 @@
#include "GDCore/Serialization/SerializerElement.h"
#include "GDCore/Tools/Localization.h"
#include "GDCore/Tools/Log.h"
#include "ParameterMetadata.h"
#include "GDCore/Extensions/Metadata/ParameterMetadata.h"
namespace gd {
InstructionMetadata::InstructionMetadata()
@@ -60,22 +60,25 @@ InstructionMetadata& InstructionMetadata::AddParameter(
info.description = description;
info.codeOnly = false;
info.SetOptional(parameterIsOptional);
info.SetExtraInfo(
gd::String fixedSupplementaryInformation =
// For objects/behavior, the supplementary information
// parameter is an object/behavior type...
((gd::ParameterMetadata::IsObject(type) ||
gd::ParameterMetadata::IsBehavior(type))
gd::ParameterMetadata::IsBehavior(type))
// Prefix with the namespace if it's not already there.
&& !(supplementaryInformation.rfind(extensionNamespace, 0) == 0))
? (supplementaryInformation.empty()
? ""
: extensionNamespace +
supplementaryInformation //... so prefix it with the
// extension
// namespace.
)
: supplementaryInformation); // Otherwise don't change anything
//... so prefix it with the extension namespace.
: extensionNamespace + supplementaryInformation)
// Otherwise don't change anything
: supplementaryInformation;
if (gd::ParameterMetadata::IsObject(type)) {
info.GetValueTypeMetadata().GetObjectType().SetName(fixedSupplementaryInformation);
} else {
info.SetExtraInfo(fixedSupplementaryInformation);
}
// TODO: Assert against supplementaryInformation === "emsc" (when running with
// Emscripten), and warn about a missing argument when calling addParameter.
@@ -212,7 +215,7 @@ InstructionMetadata::UseStandardRelationalOperatorParameters(
return *this;
}
InstructionMetadata& InstructionMetadata::SetRequiresBaseObjectCapability(
InstructionMetadata& InstructionMetadata::SetRequiredBaseObjectCapability(
const gd::String& capability) {
if (!IsObjectInstruction() && !IsBehaviorInstruction()) {
gd::LogError("Tried to add capability \"" + capability +

View File

@@ -4,8 +4,10 @@
* reserved. This project is released under the MIT License.
*/
#ifndef INSTRUCTIONMETADATA_H
#define INSTRUCTIONMETADATA_H
#pragma once
#include "AbstractFunctionMetadata.h"
#include <algorithm>
#include <functional>
#include <map>
@@ -22,7 +24,7 @@ class Layout;
class EventsCodeGenerator;
class EventsCodeGenerationContext;
class SerializerElement;
} // namespace gd
} // namespace gd
namespace gd {
@@ -33,18 +35,15 @@ namespace gd {
*
* \ingroup Events
*/
class GD_CORE_API InstructionMetadata {
public:
class GD_CORE_API InstructionMetadata : public gd::AbstractFunctionMetadata {
public:
/**
* Construct a new instruction metadata.
*/
InstructionMetadata(const gd::String &extensionNamespace,
const gd::String &name,
const gd::String &fullname,
const gd::String &description,
const gd::String &sentence,
const gd::String &group,
const gd::String &icon,
const gd::String &name, const gd::String &fullname,
const gd::String &description, const gd::String &sentence,
const gd::String &group, const gd::String &icon,
const gd::String &smallIcon);
/**
@@ -96,7 +95,7 @@ class GD_CORE_API InstructionMetadata {
* Set that the instruction is private - it can't be used outside of the
* object/ behavior that it is attached too.
*/
InstructionMetadata &SetPrivate() {
InstructionMetadata &SetPrivate() override {
isPrivate = true;
return *this;
}
@@ -133,7 +132,7 @@ class GD_CORE_API InstructionMetadata {
/**
* Set that the instruction can be used in layouts or external events.
*/
InstructionMetadata &SetRelevantForLayoutEventsOnly() {
InstructionMetadata &SetRelevantForLayoutEventsOnly() override {
relevantContext = "Layout";
return *this;
}
@@ -141,7 +140,7 @@ class GD_CORE_API InstructionMetadata {
/**
* Set that the instruction can be used in function events.
*/
InstructionMetadata &SetRelevantForFunctionEventsOnly() {
InstructionMetadata &SetRelevantForFunctionEventsOnly() override {
relevantContext = "Function";
return *this;
}
@@ -149,7 +148,7 @@ class GD_CORE_API InstructionMetadata {
/**
* Set that the instruction can be used in asynchronous function events.
*/
InstructionMetadata &SetRelevantForAsynchronousFunctionEventsOnly() {
InstructionMetadata &SetRelevantForAsynchronousFunctionEventsOnly() override {
relevantContext = "AsynchronousFunction";
return *this;
}
@@ -157,7 +156,7 @@ class GD_CORE_API InstructionMetadata {
/**
* Set that the instruction can be used in custom object events.
*/
InstructionMetadata &SetRelevantForCustomObjectEventsOnly() {
InstructionMetadata &SetRelevantForCustomObjectEventsOnly() override {
relevantContext = "Object";
return *this;
}
@@ -192,7 +191,7 @@ class GD_CORE_API InstructionMetadata {
*
* Used mainly when an instruction is deprecated.
*/
InstructionMetadata &SetHidden() {
InstructionMetadata &SetHidden() override {
hidden = true;
return *this;
}
@@ -227,11 +226,10 @@ class GD_CORE_API InstructionMetadata {
*
* \see EventsCodeGenerator::GenerateParametersCodes
*/
InstructionMetadata &AddParameter(
const gd::String &type,
const gd::String &label,
const gd::String &supplementaryInformation = "",
bool parameterIsOptional = false);
InstructionMetadata &
AddParameter(const gd::String &type, const gd::String &label,
const gd::String &supplementaryInformation = "",
bool parameterIsOptional = false) override;
/**
* \brief Add a parameter not displayed in editor.
@@ -244,8 +242,9 @@ class GD_CORE_API InstructionMetadata {
*
* \see EventsCodeGenerator::GenerateParametersCodes
*/
InstructionMetadata &AddCodeOnlyParameter(
const gd::String &type, const gd::String &supplementaryInformation);
InstructionMetadata &
AddCodeOnlyParameter(const gd::String &type,
const gd::String &supplementaryInformation) override;
/**
* \brief Set the default value used in editor (or if an optional parameter is
@@ -253,8 +252,10 @@ class GD_CORE_API InstructionMetadata {
*
* \see AddParameter
*/
InstructionMetadata &SetDefaultValue(const gd::String &defaultValue_) {
if (!parameters.empty()) parameters.back().SetDefaultValue(defaultValue_);
InstructionMetadata &
SetDefaultValue(const gd::String &defaultValue_) override {
if (!parameters.empty())
parameters.back().SetDefaultValue(defaultValue_);
return *this;
};
@@ -264,8 +265,8 @@ class GD_CORE_API InstructionMetadata {
*
* \see AddParameter
*/
InstructionMetadata &SetParameterLongDescription(
const gd::String &longDescription) {
InstructionMetadata &
SetParameterLongDescription(const gd::String &longDescription) override {
if (!parameters.empty())
parameters.back().SetLongDescription(longDescription);
return *this;
@@ -278,8 +279,38 @@ class GD_CORE_API InstructionMetadata {
*
* \see AddParameter
*/
InstructionMetadata &SetParameterExtraInfo(const gd::String &extraInfo) {
if (!parameters.empty()) parameters.back().SetExtraInfo(extraInfo);
InstructionMetadata &
SetParameterExtraInfo(const gd::String &extraInfo) override {
if (!parameters.empty())
parameters.back().SetExtraInfo(extraInfo);
return *this;
}
/**
* \brief Set the type of object accepted by the last parameter (only apply
* for object parameter).
*
* \see AddParameter
*/
InstructionMetadata &
SetParameterObjectType(const gd::ObjectType &objectType) override {
if (!parameters.empty()) {
parameters.back().GetValueTypeMetadata().SetObjectType(objectType);
}
return *this;
}
/**
* \brief Set the capabilities of the objects accepted by the last parameter
* (only apply for object parameter).
*
* \see AddParameter
*/
InstructionMetadata &
AddRequiredObjectCapabilityOnLastParameter(const gd::String &capability) {
if (!parameters.empty()) {
parameters.back().GetValueTypeMetadata().GetObjectType().AddCapability(capability);
}
return *this;
}
@@ -290,8 +321,9 @@ class GD_CORE_API InstructionMetadata {
* \note The type "string" can be declined in several subtypes.
* \see ParameterMetadata
*/
InstructionMetadata &UseStandardOperatorParameters(
const gd::String &type, const ParameterOptions &options);
InstructionMetadata &
UseStandardOperatorParameters(const gd::String &type,
const ParameterOptions &options);
/**
* \brief Add the default parameters for an instruction comparing the
@@ -300,8 +332,9 @@ class GD_CORE_API InstructionMetadata {
* \note The type "string" can be declined in several subtypes.
* \see ParameterMetadata
*/
InstructionMetadata &UseStandardRelationalOperatorParameters(
const gd::String &type, const ParameterOptions &options);
InstructionMetadata &
UseStandardRelationalOperatorParameters(const gd::String &type,
const ParameterOptions &options);
/**
* \brief Mark the instruction as an object instruction. Automatically called
@@ -337,8 +370,8 @@ class GD_CORE_API InstructionMetadata {
* that don't support this capability, so that the editor can hide the
* instruction as it does not apply to them.
*/
InstructionMetadata &SetRequiresBaseObjectCapability(
const gd::String &capability);
InstructionMetadata &
SetRequiredBaseObjectCapability(const gd::String &capability);
/**
* \brief Get the required specified capability for this (object) instruction,
@@ -383,127 +416,12 @@ class GD_CORE_API InstructionMetadata {
* \brief Defines information about how generate the code for an instruction
*/
class ExtraInformation {
public:
public:
enum AccessType { Reference, MutatorAndOrAccessor, Mutators };
ExtraInformation() : accessType(Reference), hasCustomCodeGenerator(false){};
virtual ~ExtraInformation(){};
/**
* Set the name of the function which will be called in the generated code.
* \param functionName the name of the function to call.
*/
ExtraInformation &SetFunctionName(const gd::String &functionName_) {
functionCallName = functionName_;
return *this;
}
/**
* Set the name of the function, doing asynchronous work, which will be
* called in the generated code. This function should return an asynchronous
* task (i.e: `gdjs.AsyncTask` in the JavaScript runtime).
*
* \param functionName the name of the function doing asynchronous work to
* call.
*/
ExtraInformation &SetAsyncFunctionName(const gd::String &functionName_) {
asyncFunctionCallName = functionName_;
return *this;
}
/**
* Declare if the instruction being declared is somewhat manipulating in a
* standard way.
*/
ExtraInformation &SetManipulatedType(const gd::String &type_) {
type = type_;
return *this;
}
/**
* If InstructionMetadata::ExtraInformation::SetManipulatedType was called
* with "number" or "string", this function will tell the code generator the
* name of the getter function used to retrieve the data value.
*
* Usage example:
* \code
* obj.AddAction("String",
* _("Change the string"),
* _("Change the string of a text"),
* _("the string"),
* _("Text"),
* "CppPlatform/Extensions/text24.png",
* "CppPlatform/Extensions/text_black.png");
*
* .AddParameter("object", _("Object"), "Text", false)
* .AddParameter("operator", _("Modification operator"), "string")
* .AddParameter("string", _("String"))
* .SetFunctionName("SetString").SetManipulatedType("string").SetGetter("GetString");
*
* DECLARE_END_OBJECT_ACTION()
* \endcode
*/
ExtraInformation &SetGetter(const gd::String &getter) {
optionalAssociatedInstruction = getter;
accessType = MutatorAndOrAccessor;
return *this;
}
ExtraInformation &SetMutators(
const std::map<gd::String, gd::String> &mutators) {
optionalMutators = mutators;
accessType = Mutators;
return *this;
}
/**
* \brief Erase any existing include file and add the specified include.
*/
ExtraInformation &SetIncludeFile(const gd::String &includeFile) {
includeFiles.clear();
includeFiles.push_back(includeFile);
return *this;
}
/**
* \brief Add a file to the already existing include files.
*/
ExtraInformation &AddIncludeFile(const gd::String &includeFile) {
if (std::find(includeFiles.begin(), includeFiles.end(), includeFile) ==
includeFiles.end())
includeFiles.push_back(includeFile);
return *this;
}
/**
* \brief Get the files that must be included to use the instruction.
*/
const std::vector<gd::String> &GetIncludeFiles() const {
return includeFiles;
};
ExtraInformation &SetCustomCodeGenerator(
std::function<gd::String(Instruction &instruction,
gd::EventsCodeGenerator &codeGenerator,
gd::EventsCodeGenerationContext &context)>
codeGenerator) {
hasCustomCodeGenerator = true;
customCodeGenerator = codeGenerator;
return *this;
}
ExtraInformation &RemoveCustomCodeGenerator() {
hasCustomCodeGenerator = false;
std::function<gd::String(Instruction & instruction,
gd::EventsCodeGenerator & codeGenerator,
gd::EventsCodeGenerationContext & context)>
emptyFunction;
customCodeGenerator = emptyFunction;
return *this;
}
bool HasCustomCodeGenerator() const { return hasCustomCodeGenerator; }
// TODO Move these attributes to InstructionMetadata.
gd::String functionCallName;
gd::String asyncFunctionCallName;
gd::String type;
@@ -515,75 +433,160 @@ class GD_CORE_API InstructionMetadata {
gd::EventsCodeGenerator &codeGenerator,
gd::EventsCodeGenerationContext &context)>
customCodeGenerator;
private:
std::vector<gd::String> includeFiles;
};
ExtraInformation codeExtraInformation; ///< Information about how generate
///< code for the instruction
/**
* \brief Return the structure containing the information about code
* generation for the instruction.
*/
ExtraInformation &GetCodeExtraInformation() { return codeExtraInformation; }
/**
* \brief Declare if the instruction being declared is somewhat manipulating
* in a standard way. \param type "number" or "string" \note Shortcut for
* `codeExtraInformation.SetManipulatedType(type)`.
*/
ExtraInformation &SetManipulatedType(const gd::String &type_) {
return codeExtraInformation.SetManipulatedType(type_);
}
ExtraInformation codeExtraInformation; ///< Information about how generate
///< code for the instruction
/**
* Set the name of the function which will be called in the generated code.
* \param functionName the name of the function to call.
* \note Shortcut for `codeExtraInformation.SetFunctionName`.
*/
ExtraInformation &SetFunctionName(const gd::String &functionName) {
return codeExtraInformation.SetFunctionName(functionName);
InstructionMetadata &
SetFunctionName(const gd::String &functionName_) override {
codeExtraInformation.functionCallName = functionName_;
return *this;
}
/**
* Set the name of the function, doing asynchronous work, which will be called
* in the generated code. This function should return an asynchronous task
* (i.e: `gdjs.AsyncTask` in the JavaScript runtime).
* Set the name of the function, doing asynchronous work, which will be
* called in the generated code. This function should return an asynchronous
* task (i.e: `gdjs.AsyncTask` in the JavaScript runtime).
*
* \param functionName the name of the function doing asynchronous work to
* call. \note Shortcut for `codeExtraInformation.SetAsyncFunctionName`.
* call.
*/
ExtraInformation &SetAsyncFunctionName(const gd::String &functionName) {
return codeExtraInformation.SetAsyncFunctionName(functionName);
InstructionMetadata &SetAsyncFunctionName(const gd::String &functionName_) {
codeExtraInformation.asyncFunctionCallName = functionName_;
return *this;
}
/**
* Return the name of the function which will be called in the generated code.
*/
const gd::String &GetFunctionName() {
return codeExtraInformation.functionCallName;
}
/**
* Return the name of the function, doing asynchronous work, which will be
* called in the generated code. This function should return an asynchronous
* task (i.e: `gdjs.AsyncTask` in the JavaScript runtime).
*/
const gd::String &GetAsyncFunctionName() {
return codeExtraInformation.asyncFunctionCallName;
}
/**
* \brief Declare if the instruction being declared is somewhat manipulating
* in a standard way.
*
* \param type "number" or "string"
*/
InstructionMetadata &SetManipulatedType(const gd::String &type_) {
codeExtraInformation.type = type_;
return *this;
}
/**
* If InstructionMetadata::ExtraInformation::SetManipulatedType was called
* with "number" or "string", this function will tell the code generator the
* name of the getter function used to retrieve the data value.
*
* Usage example:
* \code
* obj.AddAction("String",
* _("Change the string"),
* _("Change the string of a text"),
* _("the string"),
* _("Text"),
* "CppPlatform/Extensions/text24.png",
* "CppPlatform/Extensions/text_black.png");
*
* .AddParameter("object", _("Object"), "Text", false)
* .AddParameter("operator", _("Modification operator"), "string")
* .AddParameter("string", _("String"))
* .SetFunctionName("SetString").SetManipulatedType("string").SetGetter("GetString");
*
* DECLARE_END_OBJECT_ACTION()
* \endcode
*/
InstructionMetadata &SetGetter(const gd::String &getter) {
codeExtraInformation.optionalAssociatedInstruction = getter;
codeExtraInformation.accessType = codeExtraInformation.MutatorAndOrAccessor;
return *this;
}
InstructionMetadata &
SetMutators(const std::map<gd::String, gd::String> &mutators) {
codeExtraInformation.optionalMutators = mutators;
codeExtraInformation.accessType = codeExtraInformation.Mutators;
return *this;
}
/**
* \brief Erase any existing include file and add the specified include.
*/
InstructionMetadata &SetIncludeFile(const gd::String &includeFile) {
codeExtraInformation.SetIncludeFile(includeFile);
InstructionMetadata &SetIncludeFile(const gd::String &includeFile) override {
codeExtraInformation.includeFiles.clear();
codeExtraInformation.includeFiles.push_back(includeFile);
return *this;
}
/**
* \brief Add a file to the already existing include files.
*/
InstructionMetadata &AddIncludeFile(const gd::String &includeFile) {
codeExtraInformation.AddIncludeFile(includeFile);
InstructionMetadata &AddIncludeFile(const gd::String &includeFile) override {
if (std::find(codeExtraInformation.includeFiles.begin(),
codeExtraInformation.includeFiles.end(),
includeFile) == codeExtraInformation.includeFiles.end())
codeExtraInformation.includeFiles.push_back(includeFile);
return *this;
}
/**
* \brief Get the files that must be included to use the instruction.
*/
const std::vector<gd::String> &GetIncludeFiles() const {
return codeExtraInformation.GetIncludeFiles();
const std::vector<gd::String> &GetIncludeFiles() const override {
return codeExtraInformation.includeFiles;
};
InstructionMetadata &SetCustomCodeGenerator(
std::function<gd::String(Instruction &instruction,
gd::EventsCodeGenerator &codeGenerator,
gd::EventsCodeGenerationContext &context)>
codeGenerator) {
codeExtraInformation.hasCustomCodeGenerator = true;
codeExtraInformation.customCodeGenerator = codeGenerator;
return *this;
}
InstructionMetadata &RemoveCustomCodeGenerator() {
codeExtraInformation.hasCustomCodeGenerator = false;
std::function<gd::String(Instruction & instruction,
gd::EventsCodeGenerator & codeGenerator,
gd::EventsCodeGenerationContext & context)>
emptyFunction;
codeExtraInformation.customCodeGenerator = emptyFunction;
return *this;
}
bool HasCustomCodeGenerator() const {
return codeExtraInformation.hasCustomCodeGenerator;
}
/**
* \brief Return the structure containing the information about code
* generation for the instruction.
*
* \deprecated
*/
InstructionMetadata &GetCodeExtraInformation() { return *this; }
std::vector<ParameterMetadata> parameters;
private:
private:
gd::String fullname;
gd::String description;
gd::String helpPath;
@@ -594,8 +597,8 @@ class GD_CORE_API InstructionMetadata {
bool canHaveSubInstructions;
gd::String extensionNamespace;
bool hidden;
int usageComplexity; ///< Evaluate the instruction from 0 (simple&easy to
///< use) to 10 (complex to understand)
int usageComplexity; ///< Evaluate the instruction from 0 (simple&easy to
///< use) to 10 (complex to understand)
bool isPrivate;
bool isObjectInstruction;
bool isBehaviorInstruction;
@@ -603,6 +606,4 @@ class GD_CORE_API InstructionMetadata {
gd::String relevantContext;
};
} // namespace gd
#endif // INSTRUCTIONMETADATA_H
} // namespace gd

View File

@@ -0,0 +1,201 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#pragma once
#include <map>
#include "GDCore/Extensions/Metadata/ExpressionMetadata.h"
#include "GDCore/Extensions/Metadata/InstructionMetadata.h"
#include "GDCore/String.h"
namespace gd {
class Behavior;
class BehaviorsSharedData;
class MultipleInstructionMetadata;
class InstructionMetadata;
class ExpressionMetadata;
} // namespace gd
namespace gd {
/**
* \brief Contains user-friendly information about instructions and expressions
* (usually for a behavior or an object).
*
* \ingroup Events
*/
class GD_CORE_API InstructionOrExpressionContainerMetadata {
public:
InstructionOrExpressionContainerMetadata(){};
virtual ~InstructionOrExpressionContainerMetadata(){};
/**
* Declare a new condition as being part of the behavior or object.
* \deprecated Prefer using `AddScopedCondition`, to properly namespace
* the condition.
*/
virtual gd::InstructionMetadata &
AddCondition(const gd::String &name_, const gd::String &fullname_,
const gd::String &description_, const gd::String &sentence_,
const gd::String &group_, const gd::String &icon_,
const gd::String &smallicon_) = 0;
/**
* Declare a new action as being part of the behavior or object.
* \deprecated Prefer using `AddScopedAction`, to properly namespace
* the action.
*/
virtual gd::InstructionMetadata &
AddAction(const gd::String &name_, const gd::String &fullname_,
const gd::String &description_, const gd::String &sentence_,
const gd::String &group_, const gd::String &icon_,
const gd::String &smallicon_) = 0;
/**
* Declare a new condition as being part of the behavior or object.
*/
virtual gd::InstructionMetadata &
AddScopedCondition(const gd::String &name_, const gd::String &fullname_,
const gd::String &description_,
const gd::String &sentence_, const gd::String &group_,
const gd::String &icon_, const gd::String &smallicon_) = 0;
/**
* Declare a new action as being part of the behavior or object.
*/
virtual gd::InstructionMetadata &
AddScopedAction(const gd::String &name_, const gd::String &fullname_,
const gd::String &description_, const gd::String &sentence_,
const gd::String &group_, const gd::String &icon_,
const gd::String &smallicon_) = 0;
/**
* Declare a new action as being part of the extension.
*/
virtual gd::ExpressionMetadata &
AddExpression(const gd::String &name_, const gd::String &fullname_,
const gd::String &description_, const gd::String &group_,
const gd::String &smallicon_) = 0;
/**
* Declare a new string expression as being part of the extension.
*/
virtual gd::ExpressionMetadata &
AddStrExpression(const gd::String &name_, const gd::String &fullname_,
const gd::String &description_, const gd::String &group_,
const gd::String &smallicon_) = 0;
/**
* \brief Declare a new expression and condition as being part of the
* behavior.
* \note It's recommended to use this function to avoid declaring twice a
* similar expression/condition.
*/
virtual gd::MultipleInstructionMetadata AddExpressionAndCondition(
const gd::String &type, const gd::String &name,
const gd::String &fullname, const gd::String &description,
const gd::String &sentenceName, const gd::String &group,
const gd::String &icon) = 0;
/**
* \brief Declare a new expression, condition and action as being part of the
* behavior.
* \note The action name is prefixed by "Set" (and the namespace, as the
* condition).
* \note It's recommended to use this function to avoid declaring 3 times a
* similar expression/condition/action.
*/
virtual gd::MultipleInstructionMetadata AddExpressionAndConditionAndAction(
const gd::String &type, const gd::String &name,
const gd::String &fullname, const gd::String &description,
const gd::String &sentenceName, const gd::String &group,
const gd::String &icon) = 0;
/**
* \brief Create a new action which is the duplicate of the specified one.
*
* Useful for handling a deprecated action that is just a "copy" of the new
* one.
*/
virtual gd::InstructionMetadata &
AddDuplicatedAction(const gd::String &newActionName,
const gd::String &copiedActionName) = 0;
/**
* \brief Create a new condition which is the duplicate of the specified one.
*
* Useful for handling a deprecated condition that is just a "copy" of the new
* one.
*/
virtual gd::InstructionMetadata &
AddDuplicatedCondition(const gd::String &newConditionName,
const gd::String &copiedConditionName) = 0;
virtual InstructionOrExpressionContainerMetadata &
SetFullName(const gd::String &fullname_) = 0;
virtual InstructionOrExpressionContainerMetadata &
SetDescription(const gd::String &description_) = 0;
/**
* \brief Erase any existing include file and add the specified include.
* \note The requirement may vary depending on the platform: Most of the time,
* the include file contains the declaration of the behavior.
*/
virtual InstructionOrExpressionContainerMetadata &
SetIncludeFile(const gd::String &includeFile) = 0;
/**
* \brief Add a file to the already existing include files.
*/
virtual InstructionOrExpressionContainerMetadata &
AddIncludeFile(const gd::String &includeFile) = 0;
/**
* Get the help path of the behavior, relative to the GDevelop documentation
* root.
*/
virtual const gd::String &GetHelpPath() const = 0;
/**
* Set the help path of the behavior, relative to the GDevelop documentation
* root.
*
* The behavior instructions will have this help path set by
* default, unless you call SetHelpPath on them.
*/
virtual InstructionOrExpressionContainerMetadata &
SetHelpPath(const gd::String &path) = 0;
virtual const gd::String &GetName() const = 0;
virtual const gd::String &GetFullName() const = 0;
virtual const gd::String &GetDescription() const = 0;
virtual const gd::String &GetIconFilename() const = 0;
/**
* \brief Return a reference to a map containing the names of the actions
* (as keys) and the metadata associated with (as values).
*/
virtual std::map<gd::String, gd::InstructionMetadata> &GetAllActions() = 0;
/**
* \see gd::PlatformExtension::GetAllActions
*/
virtual std::map<gd::String, gd::InstructionMetadata> &GetAllConditions() = 0;
/**
* \see gd::PlatformExtension::GetAllActions
*/
virtual std::map<gd::String, gd::ExpressionMetadata> &GetAllExpressions() = 0;
/**
* \see gd::PlatformExtension::GetAllActions
*/
virtual std::map<gd::String, gd::ExpressionMetadata> &
GetAllStrExpressions() = 0;
private:
};
} // namespace gd

View File

@@ -1,12 +0,0 @@
/*
* GDevelop Core
* Copyright 2008-present Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#include "MultipleInstructionMetadata.h"
#include "InstructionMetadata.h"
namespace gd {
} // namespace gd

View File

@@ -3,8 +3,8 @@
* Copyright 2008-present Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#ifndef MULTIPLEINSTRUCTIONSMETADATA_H
#define MULTIPLEINSTRUCTIONSMETADATA_H
#pragma once
#include "GDCore/Extensions/Metadata/ExpressionMetadata.h"
#include "GDCore/Extensions/Metadata/InstructionMetadata.h"
#include "GDCore/String.h"
@@ -21,7 +21,7 @@ namespace gd {
*
* \ingroup PlatformDefinition
*/
class GD_CORE_API MultipleInstructionMetadata {
class GD_CORE_API MultipleInstructionMetadata : public AbstractFunctionMetadata {
public:
static MultipleInstructionMetadata WithExpressionAndCondition(
gd::ExpressionMetadata &expression, gd::InstructionMetadata &condition) {
@@ -45,7 +45,7 @@ class GD_CORE_API MultipleInstructionMetadata {
const gd::String &type,
const gd::String &label,
const gd::String &supplementaryInformation = "",
bool parameterIsOptional = false) {
bool parameterIsOptional = false) override {
if (expression)
expression->AddParameter(
type, label, supplementaryInformation, parameterIsOptional);
@@ -62,7 +62,7 @@ class GD_CORE_API MultipleInstructionMetadata {
* \see gd::InstructionMetadata::AddCodeOnlyParameter
*/
MultipleInstructionMetadata &AddCodeOnlyParameter(
const gd::String &type, const gd::String &supplementaryInformation) {
const gd::String &type, const gd::String &supplementaryInformation) override {
if (expression)
expression->AddCodeOnlyParameter(type, supplementaryInformation);
if (condition)
@@ -74,7 +74,7 @@ class GD_CORE_API MultipleInstructionMetadata {
/**
* \see gd::InstructionMetadata::SetDefaultValue
*/
MultipleInstructionMetadata &SetDefaultValue(const gd::String &defaultValue) {
MultipleInstructionMetadata &SetDefaultValue(const gd::String &defaultValue) override {
if (expression) expression->SetDefaultValue(defaultValue);
if (condition) condition->SetDefaultValue(defaultValue);
if (action) action->SetDefaultValue(defaultValue);
@@ -85,18 +85,52 @@ class GD_CORE_API MultipleInstructionMetadata {
* \see gd::InstructionMetadata::SetParameterExtraInfo
*/
MultipleInstructionMetadata &SetParameterExtraInfo(
const gd::String &defaultValue) {
if (expression) expression->SetParameterExtraInfo(defaultValue);
if (condition) condition->SetParameterExtraInfo(defaultValue);
if (action) action->SetParameterExtraInfo(defaultValue);
const gd::String &extraInfo) override {
if (expression) expression->SetParameterExtraInfo(extraInfo);
if (condition) condition->SetParameterExtraInfo(extraInfo);
if (action) action->SetParameterExtraInfo(extraInfo);
return *this;
};
/**
* \see gd::InstructionMetadata::SetParameterObjectType
*/
MultipleInstructionMetadata &
SetParameterObjectType(const gd::ObjectType &objectType) override {
if (expression) {
expression->SetParameterObjectType(objectType);
}
if (condition) {
condition->SetParameterObjectType(objectType);
}
if (action) {
action->SetParameterObjectType(objectType);
}
return *this;
}
/**
* \see gd::InstructionMetadata::AddRequiredObjectCapabilityOnLastParameter
*/
MultipleInstructionMetadata &
AddRequiredObjectCapabilityOnLastParameter(const gd::String &capability) {
if (expression) {
expression->AddRequiredObjectCapabilityOnLastParameter(capability);
}
if (condition) {
condition->AddRequiredObjectCapabilityOnLastParameter(capability);
}
if (action) {
action->AddRequiredObjectCapabilityOnLastParameter(capability);
}
return *this;
}
/**
* \see gd::InstructionMetadata::SetParameterLongDescription
*/
MultipleInstructionMetadata &SetParameterLongDescription(
const gd::String &longDescription) {
const gd::String &longDescription) override {
if (expression) expression->SetParameterLongDescription(longDescription);
if (condition) condition->SetParameterLongDescription(longDescription);
if (action) action->SetParameterLongDescription(longDescription);
@@ -106,7 +140,7 @@ class GD_CORE_API MultipleInstructionMetadata {
/**
* \see gd::InstructionMetadata::SetHidden
*/
MultipleInstructionMetadata &SetHidden() {
MultipleInstructionMetadata &SetHidden() override {
if (expression) expression->SetHidden();
if (condition) condition->SetHidden();
if (action) action->SetHidden();
@@ -114,13 +148,13 @@ class GD_CORE_API MultipleInstructionMetadata {
};
/**
* \see gd::InstructionMetadata::SetRequiresBaseObjectCapability
* \see gd::InstructionMetadata::SetRequiredBaseObjectCapability
*/
MultipleInstructionMetadata &SetRequiresBaseObjectCapability(
MultipleInstructionMetadata &SetRequiredBaseObjectCapability(
const gd::String &capability) {
if (expression) expression->SetRequiresBaseObjectCapability(capability);
if (condition) condition->SetRequiresBaseObjectCapability(capability);
if (action) action->SetRequiresBaseObjectCapability(capability);
if (expression) expression->SetRequiredBaseObjectCapability(capability);
if (condition) condition->SetRequiredBaseObjectCapability(capability);
if (action) action->SetRequiredBaseObjectCapability(capability);
return *this;
}
@@ -136,47 +170,47 @@ class GD_CORE_API MultipleInstructionMetadata {
return *this;
}
MultipleInstructionMetadata &SetFunctionName(const gd::String &functionName) {
MultipleInstructionMetadata &SetFunctionName(const gd::String &functionName) override {
if (expression) expression->SetFunctionName(functionName);
if (condition) condition->SetFunctionName(functionName);
if (action) action->GetCodeExtraInformation().SetFunctionName(functionName);
if (action) action->SetFunctionName(functionName);
return *this;
}
MultipleInstructionMetadata &SetGetter(const gd::String &getter) {
if (expression) expression->SetFunctionName(getter);
if (condition) condition->SetFunctionName(getter);
if (action) action->GetCodeExtraInformation().SetGetter(getter);
if (action) action->SetGetter(getter);
return *this;
}
MultipleInstructionMetadata &SetIncludeFile(const gd::String &includeFile) {
MultipleInstructionMetadata &SetIncludeFile(const gd::String &includeFile) override {
if (expression)
expression->GetCodeExtraInformation().SetIncludeFile(includeFile);
expression->SetIncludeFile(includeFile);
if (condition)
condition->GetCodeExtraInformation().SetIncludeFile(includeFile);
if (action) action->GetCodeExtraInformation().SetIncludeFile(includeFile);
condition->SetIncludeFile(includeFile);
if (action) action->SetIncludeFile(includeFile);
return *this;
}
MultipleInstructionMetadata &AddIncludeFile(const gd::String &includeFile) {
MultipleInstructionMetadata &AddIncludeFile(const gd::String &includeFile) override {
if (expression)
expression->GetCodeExtraInformation().AddIncludeFile(includeFile);
if (condition)
condition->GetCodeExtraInformation().AddIncludeFile(includeFile);
if (action) action->GetCodeExtraInformation().AddIncludeFile(includeFile);
condition->AddIncludeFile(includeFile);
if (action) action->AddIncludeFile(includeFile);
return *this;
}
/**
* \brief Get the files that must be included to use the instruction.
*/
const std::vector<gd::String> &GetIncludeFiles() const {
const std::vector<gd::String> &GetIncludeFiles() const override {
if (expression)
return expression->GetCodeExtraInformation().GetIncludeFiles();
if (condition)
return condition->GetCodeExtraInformation().GetIncludeFiles();
if (action) return action->GetCodeExtraInformation().GetIncludeFiles();
return condition->GetIncludeFiles();
if (action) return action->GetIncludeFiles();
// It can't actually happen.
throw std::logic_error("no instruction metadata");
}
@@ -184,7 +218,7 @@ class GD_CORE_API MultipleInstructionMetadata {
/**
* \see gd::InstructionMetadata::SetPrivate
*/
MultipleInstructionMetadata &SetPrivate() {
MultipleInstructionMetadata &SetPrivate() override {
if (expression) expression->SetPrivate();
if (condition) condition->SetPrivate();
if (action) action->SetPrivate();
@@ -218,6 +252,42 @@ class GD_CORE_API MultipleInstructionMetadata {
return *this;
}
/**
* Set that the instruction can be used in layouts or external events.
*/
MultipleInstructionMetadata &SetRelevantForLayoutEventsOnly() override {
if (condition) condition->SetRelevantForLayoutEventsOnly();
if (action) action->SetRelevantForLayoutEventsOnly();
return *this;
}
/**
* Set that the instruction can be used in function events.
*/
MultipleInstructionMetadata &SetRelevantForFunctionEventsOnly() override {
if (condition) condition->SetRelevantForFunctionEventsOnly();
if (action) action->SetRelevantForFunctionEventsOnly();
return *this;
}
/**
* Set that the instruction can be used in asynchronous function events.
*/
MultipleInstructionMetadata &SetRelevantForAsynchronousFunctionEventsOnly() override {
if (condition) condition->SetRelevantForAsynchronousFunctionEventsOnly();
if (action) action->SetRelevantForAsynchronousFunctionEventsOnly();
return *this;
}
/**
* Set that the instruction can be used in custom object events.
*/
MultipleInstructionMetadata &SetRelevantForCustomObjectEventsOnly() override {
if (condition) condition->SetRelevantForCustomObjectEventsOnly();
if (action) action->SetRelevantForCustomObjectEventsOnly();
return *this;
}
/**
* \brief Don't use, only here to fulfill Emscripten bindings requirements.
*/
@@ -242,5 +312,3 @@ class GD_CORE_API MultipleInstructionMetadata {
};
} // namespace gd
#endif // MULTIPLEINSTRUCTIONSMETADATA_H

View File

@@ -39,6 +39,7 @@ ObjectMetadata::ObjectMetadata(const gd::String& extensionNamespace_,
return blueprintObject_->Clone();
}) {
blueprintObject = blueprintObject_;
supportedBaseObjectCapabilities.insert("effect");
}
ObjectMetadata::ObjectMetadata(const gd::String& extensionNamespace_,
@@ -56,7 +57,9 @@ ObjectMetadata::ObjectMetadata(const gd::String& extensionNamespace_,
"Error: Event-based objects don't have blueprint. "
"This method should not never be called.");
return nullptr;
}) {}
}) {
supportedBaseObjectCapabilities.insert("effect");
}
ObjectMetadata::ObjectMetadata(const gd::String& extensionNamespace_,
const gd::String& name_,
@@ -70,6 +73,7 @@ ObjectMetadata::ObjectMetadata(const gd::String& extensionNamespace_,
extensionNamespace(extensionNamespace_) {
SetFullName(gd::String(fullname_));
SetDescription(gd::String(description_));
supportedBaseObjectCapabilities.insert("effect");
}
gd::InstructionMetadata& ObjectMetadata::AddCondition(

View File

@@ -3,8 +3,10 @@
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#ifndef OBJECTMETADATA_H
#define OBJECTMETADATA_H
#pragma once
#include "InstructionOrExpressionContainerMetadata.h"
#include <functional>
#include <map>
#include <set>
@@ -32,7 +34,7 @@ namespace gd {
*
* \ingroup Events
*/
class GD_CORE_API ObjectMetadata {
class GD_CORE_API ObjectMetadata : public InstructionOrExpressionContainerMetadata {
public:
/**
* \brief Construct an object metadata, using a "blueprint" object that will
@@ -79,7 +81,7 @@ class GD_CORE_API ObjectMetadata {
const gd::String& sentence_,
const gd::String& group_,
const gd::String& icon_,
const gd::String& smallicon_);
const gd::String& smallicon_) override;
/**
* \brief Declare a new action as being part of the extension.
@@ -92,7 +94,7 @@ class GD_CORE_API ObjectMetadata {
const gd::String& sentence_,
const gd::String& group_,
const gd::String& icon_,
const gd::String& smallicon_);
const gd::String& smallicon_) override;
/**
* Declare a new condition as being part of the object.
@@ -103,7 +105,7 @@ class GD_CORE_API ObjectMetadata {
const gd::String& sentence_,
const gd::String& group_,
const gd::String& icon_,
const gd::String& smallicon_);
const gd::String& smallicon_) override;
/**
* Declare a new action as being part of the object.
@@ -114,7 +116,7 @@ class GD_CORE_API ObjectMetadata {
const gd::String& sentence_,
const gd::String& group_,
const gd::String& icon_,
const gd::String& smallicon_);
const gd::String& smallicon_) override;
/**
* \brief Declare a new expression as being part of the extension.
@@ -123,7 +125,7 @@ class GD_CORE_API ObjectMetadata {
const gd::String& fullname_,
const gd::String& description_,
const gd::String& group_,
const gd::String& smallicon_);
const gd::String& smallicon_) override;
/**
* \brief Declare a new string expression as being part of the extension.
*/
@@ -131,7 +133,7 @@ class GD_CORE_API ObjectMetadata {
const gd::String& fullname_,
const gd::String& description_,
const gd::String& group_,
const gd::String& smallicon_);
const gd::String& smallicon_) override;
/**
* \brief Declare a new expression and condition as being part of the
@@ -146,7 +148,7 @@ class GD_CORE_API ObjectMetadata {
const gd::String& description,
const gd::String& sentenceName,
const gd::String& group,
const gd::String& icon);
const gd::String& icon) override;
/**
* \brief Declare a new expression, condition and action as being part of the
@@ -163,7 +165,7 @@ class GD_CORE_API ObjectMetadata {
const gd::String& description,
const gd::String& sentenceName,
const gd::String& group,
const gd::String& icon);
const gd::String& icon) override;
/**
* \brief Create a new action which is the duplicate of the specified one.
@@ -172,7 +174,7 @@ class GD_CORE_API ObjectMetadata {
* one.
*/
gd::InstructionMetadata& AddDuplicatedAction(
const gd::String& newActionName, const gd::String& copiedActionName);
const gd::String& newActionName, const gd::String& copiedActionName) override;
/**
* \brief Create a new condition which is the duplicate of the specified one.
@@ -182,23 +184,23 @@ class GD_CORE_API ObjectMetadata {
*/
gd::InstructionMetadata& AddDuplicatedCondition(
const gd::String& newConditionName,
const gd::String& copiedConditionName);
const gd::String& copiedConditionName) override;
/**
* \brief Set the name shown to the user.
*/
ObjectMetadata& SetFullName(const gd::String& fullname_);
ObjectMetadata& SetFullName(const gd::String& fullname_) override;
/**
* \brief Set the description shown to the user.
*/
ObjectMetadata& SetDescription(const gd::String& description_);
ObjectMetadata& SetDescription(const gd::String& description_) override;
/**
* \brief Get the help path of the object, relative to the GDevelop
* documentation root.
*/
const gd::String& GetHelpPath() const { return helpPath; }
const gd::String& GetHelpPath() const override { return helpPath; }
/**
* \brief Set the help path of the object, relative to the GDevelop
@@ -207,7 +209,7 @@ class GD_CORE_API ObjectMetadata {
* The object instructions will have this help path set by
* default, unless you call SetHelpPath on them.
*/
ObjectMetadata& SetHelpPath(const gd::String& path) {
ObjectMetadata& SetHelpPath(const gd::String& path) override {
helpPath = path;
return *this;
}
@@ -223,37 +225,49 @@ class GD_CORE_API ObjectMetadata {
/**
* \brief The "capabilities" that are offered by the base object that are
* *not* supported by this object, and should be hidden in the editor
* supported by this object, and should *not* be hidden in the editor
* interface.
*/
const std::set<gd::String>& GetUnsupportedBaseObjectCapabilities() const {
return unsupportedBaseObjectCapabilities;
const std::set<gd::String>& GetSupportedBaseObjectCapabilities() const {
return supportedBaseObjectCapabilities;
}
/**
* \brief Add a "capability" that is offered by the base object that is *not*
* supported by this object, and should be hidden in the editor interface.
* \brief Add a "capability" that is offered by the base object that is
* supported by this object, and should *not* be hidden in the editor interface.
*/
ObjectMetadata& AddUnsupportedBaseObjectCapability(
ObjectMetadata& MarkBaseObjectCapabilityAsSupported(
const gd::String& capability) {
unsupportedBaseObjectCapabilities.insert(capability);
supportedBaseObjectCapabilities.insert(capability);
return *this;
}
/**
* \brief Check if a "capability" that is offered by the base object is *not*
* \brief Remove a "capability" that is offered by the base object that is *not*
* supported by this object, and should be hidden in the editor interface.
*/
bool IsUnsupportedBaseObjectCapability(const gd::String& capability) const {
return unsupportedBaseObjectCapabilities.find(capability) != unsupportedBaseObjectCapabilities.end();
ObjectMetadata& MarkBaseObjectCapabilityAsUnsupported(
const gd::String& capability) {
supportedBaseObjectCapabilities.erase(capability);
return *this;
}
const gd::String& GetName() const { return name; }
const gd::String& GetFullName() const { return fullname; }
/**
* \brief Check if a "capability" that is offered by the base object is
* supported by this object, and should *not* be hidden in the editor interface.
*/
bool IsSupportedBaseObjectCapability(const gd::String& capability) const {
return capability.empty() ||
supportedBaseObjectCapabilities.find(capability) !=
supportedBaseObjectCapabilities.end();
}
const gd::String& GetName() const override { return name; }
const gd::String& GetFullName() const override { return fullname; }
const gd::String& GetCategoryFullName() const { return categoryFullName; }
const gd::String& GetHelpUrl() const { return helpUrl; }
const gd::String& GetDescription() const { return description; }
const gd::String& GetIconFilename() const { return iconFilename; }
const gd::String& GetDescription() const override { return description; }
const gd::String& GetIconFilename() const override { return iconFilename; }
/**
* \brief Set the URL pointing to the help page about this object
@@ -267,33 +281,33 @@ class GD_CORE_API ObjectMetadata {
* \note The requirement may vary depending on the platform: Most of the time,
* the include file contains the declaration of the object.
*/
ObjectMetadata& SetIncludeFile(const gd::String& includeFile);
ObjectMetadata& SetIncludeFile(const gd::String& includeFile) override;
/**
* \brief Add a file to the already existing include files.
*/
ObjectMetadata& AddIncludeFile(const gd::String& includeFile);
ObjectMetadata& AddIncludeFile(const gd::String& includeFile) override;
/**
* \brief Return a reference to a map containing the names of the actions
* (as keys) and the metadata associated with (as values).
*/
std::map<gd::String, gd::InstructionMetadata>& GetAllActions() { return actionsInfos; };
std::map<gd::String, gd::InstructionMetadata>& GetAllActions() override { return actionsInfos; };
/**
* \see gd::PlatformExtension::GetAllActions
*/
std::map<gd::String, gd::InstructionMetadata>& GetAllConditions() { return conditionsInfos; };
std::map<gd::String, gd::InstructionMetadata>& GetAllConditions() override { return conditionsInfos; };
/**
* \see gd::PlatformExtension::GetAllActions
*/
std::map<gd::String, gd::ExpressionMetadata>& GetAllExpressions() { return expressionsInfos; };
std::map<gd::String, gd::ExpressionMetadata>& GetAllExpressions() override { return expressionsInfos; };
/**
* \see gd::PlatformExtension::GetAllActions
*/
std::map<gd::String, gd::ExpressionMetadata>& GetAllStrExpressions() { return strExpressionsInfos; };
std::map<gd::String, gd::ExpressionMetadata>& GetAllStrExpressions() override { return strExpressionsInfos; };
/**
* \brief Set the object to be hidden in the IDE.
@@ -329,7 +343,7 @@ class GD_CORE_API ObjectMetadata {
gd::String description;
gd::String iconFilename;
gd::String categoryFullName;
std::set<gd::String> unsupportedBaseObjectCapabilities;
std::set<gd::String> supportedBaseObjectCapabilities;
bool hidden = false;
std::shared_ptr<gd::ObjectConfiguration>
@@ -341,4 +355,3 @@ class GD_CORE_API ObjectMetadata {
};
} // namespace gd
#endif // OBJECTMETADATA_H

View File

@@ -11,6 +11,7 @@
#include "GDCore/String.h"
#include "GDCore/Extensions/Metadata/ValueTypeMetadata.h"
#include "GDCore/Project/ObjectType.h"
namespace gd {
class SerializerElement;
@@ -34,6 +35,11 @@ class GD_CORE_API ParameterMetadata {
*/
gd::ValueTypeMetadata &GetValueTypeMetadata() { return valueTypeMetadata; }
/**
* \brief Return the metadata of the parameter type.
*/
const gd::ValueTypeMetadata &GetValueTypeMetadata() const { return valueTypeMetadata; }
/**
* \brief Set the metadata of the parameter type.
*/

View File

@@ -27,9 +27,10 @@ void ParameterMetadataTools::ParametersToObjectsContainer(
if (parameter.GetName().empty()) continue;
if (gd::ParameterMetadata::IsObject(parameter.GetType())) {
// TODO Declare object capabilities
outputObjectsContainer.InsertNewObject(
project,
parameter.GetExtraInfo(),
parameter.GetValueTypeMetadata().GetObjectType().GetName(),
parameter.GetName(),
outputObjectsContainer.GetObjectsCount());

View File

@@ -7,6 +7,7 @@
#include "GDCore/CommonTools.h"
#include "GDCore/Serialization/SerializerElement.h"
#include "GDCore/Extensions/Metadata/ParameterMetadata.h"
namespace gd {
@@ -17,6 +18,9 @@ void ValueTypeMetadata::SerializeTo(SerializerElement& element) const {
if (!supplementaryInformation.empty()) {
element.SetAttribute("supplementaryInformation", supplementaryInformation);
}
if (gd::ParameterMetadata::IsObject(name)) {
objectType.SerializeTo(element);
}
if (optional) {
element.SetAttribute("optional", optional);
}
@@ -29,6 +33,16 @@ void ValueTypeMetadata::UnserializeFrom(const SerializerElement& element) {
name = element.GetStringAttribute("type");
supplementaryInformation =
element.GetStringAttribute("supplementaryInformation");
if (gd::ParameterMetadata::IsObject(name)) {
objectType.UnserializeFrom(element);
// Compatibility with GD <= 4.2.166
if (!element.HasAttribute("objectType") && !supplementaryInformation.empty()) {
objectType.SetName(supplementaryInformation);
supplementaryInformation = "";
}
std::cout << "Unserialized object type: " << objectType.GetName() << std::endl;
}
// end of compatibility code
optional = element.GetBoolAttribute("optional");
defaultValue = element.GetStringAttribute("defaultValue");
}

View File

@@ -9,6 +9,7 @@
#include <map>
#include <memory>
#include "GDCore/Project/ObjectType.h"
#include "GDCore/String.h"
namespace gd {
class SerializerElement;
@@ -58,6 +59,23 @@ class GD_CORE_API ValueTypeMetadata {
return *this;
}
/**
* \brief Get the object type.
*/
gd::ObjectType& GetObjectType() { return objectType; };
/**
* \brief Get the type of the object.
*/
const gd::ObjectType& GetObjectType() const { return objectType; }
/**
* \brief Set the type of the object.
*/
void SetObjectType(const gd::ObjectType& objectType_) {
objectType = objectType_;
}
/**
* \brief Return true if the parameter is optional.
*/
@@ -237,6 +255,7 @@ class GD_CORE_API ValueTypeMetadata {
private:
gd::String name; ///< Parameter type
gd::String supplementaryInformation; ///< Used if needed
gd::ObjectType objectType;
bool optional; ///< True if the parameter is optional
gd::String defaultValue; ///< Used as a default value in editor or if an
///< optional parameter is empty.

View File

@@ -653,7 +653,7 @@ void PlatformExtension::StripUnimplementedInstructionsAndExpressions() {
GetAllActions().begin();
it != GetAllActions().end();) {
if (it->second.codeExtraInformation.functionCallName.empty() &&
!it->second.codeExtraInformation.HasCustomCodeGenerator()) {
!it->second.HasCustomCodeGenerator()) {
GetAllActions().erase(it++);
} else
++it;
@@ -663,7 +663,7 @@ void PlatformExtension::StripUnimplementedInstructionsAndExpressions() {
GetAllConditions().begin();
it != GetAllConditions().end();) {
if (it->second.codeExtraInformation.functionCallName.empty() &&
!it->second.codeExtraInformation.HasCustomCodeGenerator()) {
!it->second.HasCustomCodeGenerator()) {
GetAllConditions().erase(it++);
} else
++it;
@@ -673,7 +673,7 @@ void PlatformExtension::StripUnimplementedInstructionsAndExpressions() {
GetAllExpressions().begin();
it != GetAllExpressions().end();) {
if (it->second.codeExtraInformation.functionCallName.empty() &&
!it->second.codeExtraInformation.HasCustomCodeGenerator()) {
!it->second.HasCustomCodeGenerator()) {
GetAllExpressions().erase(it++);
} else
++it;
@@ -683,7 +683,7 @@ void PlatformExtension::StripUnimplementedInstructionsAndExpressions() {
GetAllStrExpressions().begin();
it != GetAllStrExpressions().end();) {
if (it->second.codeExtraInformation.functionCallName.empty() &&
!it->second.codeExtraInformation.HasCustomCodeGenerator()) {
!it->second.HasCustomCodeGenerator()) {
GetAllStrExpressions().erase(it++);
} else
++it;
@@ -699,7 +699,7 @@ void PlatformExtension::StripUnimplementedInstructionsAndExpressions() {
obj.actionsInfos.begin();
it != obj.actionsInfos.end();) {
if (it->second.codeExtraInformation.functionCallName.empty() &&
!it->second.codeExtraInformation.HasCustomCodeGenerator()) {
!it->second.HasCustomCodeGenerator()) {
obj.actionsInfos.erase(it++);
} else
++it;
@@ -709,7 +709,7 @@ void PlatformExtension::StripUnimplementedInstructionsAndExpressions() {
obj.conditionsInfos.begin();
it != obj.conditionsInfos.end();) {
if (it->second.codeExtraInformation.functionCallName.empty() &&
!it->second.codeExtraInformation.HasCustomCodeGenerator()) {
!it->second.HasCustomCodeGenerator()) {
obj.conditionsInfos.erase(it++);
} else
++it;
@@ -719,7 +719,7 @@ void PlatformExtension::StripUnimplementedInstructionsAndExpressions() {
obj.expressionsInfos.begin();
it != obj.expressionsInfos.end();) {
if (it->second.codeExtraInformation.functionCallName.empty() &&
!it->second.codeExtraInformation.HasCustomCodeGenerator()) {
!it->second.HasCustomCodeGenerator()) {
obj.expressionsInfos.erase(it++);
} else
++it;
@@ -729,7 +729,7 @@ void PlatformExtension::StripUnimplementedInstructionsAndExpressions() {
obj.strExpressionsInfos.begin();
it != obj.strExpressionsInfos.end();) {
if (it->second.codeExtraInformation.functionCallName.empty() &&
!it->second.codeExtraInformation.HasCustomCodeGenerator()) {
!it->second.HasCustomCodeGenerator()) {
obj.strExpressionsInfos.erase(it++);
} else
++it;
@@ -746,7 +746,7 @@ void PlatformExtension::StripUnimplementedInstructionsAndExpressions() {
obj.actionsInfos.begin();
it != obj.actionsInfos.end();) {
if (it->second.codeExtraInformation.functionCallName.empty() &&
!it->second.codeExtraInformation.HasCustomCodeGenerator()) {
!it->second.HasCustomCodeGenerator()) {
obj.actionsInfos.erase(it++);
} else
++it;
@@ -756,7 +756,7 @@ void PlatformExtension::StripUnimplementedInstructionsAndExpressions() {
obj.conditionsInfos.begin();
it != obj.conditionsInfos.end();) {
if (it->second.codeExtraInformation.functionCallName.empty() &&
!it->second.codeExtraInformation.HasCustomCodeGenerator()) {
!it->second.HasCustomCodeGenerator()) {
obj.conditionsInfos.erase(it++);
} else
++it;
@@ -766,7 +766,7 @@ void PlatformExtension::StripUnimplementedInstructionsAndExpressions() {
obj.expressionsInfos.begin();
it != obj.expressionsInfos.end();) {
if (it->second.codeExtraInformation.functionCallName.empty() &&
!it->second.codeExtraInformation.HasCustomCodeGenerator()) {
!it->second.HasCustomCodeGenerator()) {
obj.expressionsInfos.erase(it++);
} else
++it;
@@ -776,7 +776,7 @@ void PlatformExtension::StripUnimplementedInstructionsAndExpressions() {
obj.strExpressionsInfos.begin();
it != obj.strExpressionsInfos.end();) {
if (it->second.codeExtraInformation.functionCallName.empty() &&
!it->second.codeExtraInformation.HasCustomCodeGenerator()) {
!it->second.HasCustomCodeGenerator()) {
obj.strExpressionsInfos.erase(it++);
} else
++it;

View File

@@ -19,6 +19,8 @@
#include "GDCore/Project/Project.h"
#include "GDCore/Project/ExternalEvents.h"
#include "GDCore/IDE/DependenciesAnalyzer.h"
#include "GDCore/Extensions/Metadata/ParameterMetadataTools.h"
using namespace std;
@@ -97,8 +99,9 @@ class GD_CORE_API IdentifierFinderExpressionNodeWorker
auto& parameterNode = node.parameters[parameterIndex];
++parameterIndex;
if (considerFunction && parameterMetadata.GetType() == "identifier"
&& parameterMetadata.GetExtraInfo() == identifierType) {
if (considerFunction &&
parameterMetadata.GetType() == "identifier" &&
parameterMetadata.GetExtraInfo() == identifierType) {
// Store the value of the parameter
results.insert(
gd::ExpressionParser2NodePrinter::PrintNode(*parameterNode));
@@ -149,8 +152,8 @@ class GD_CORE_API IdentifierFinderEventWorker
platform, instruction.GetType());
for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
// The parameter has the searched type...
if (instrInfos.parameters[pNb].GetType() == "identifier"
&& instrInfos.parameters[pNb].GetExtraInfo() == identifierType) {
if (instrInfos.parameters[pNb].GetType() == "identifier" &&
instrInfos.parameters[pNb].GetExtraInfo() == identifierType) {
//...remember the value of the parameter.
if (objectName.empty() || lastObjectParameter == objectName) {
results.insert(instruction.GetParameter(pNb).GetPlainString());
@@ -158,9 +161,9 @@ class GD_CORE_API IdentifierFinderEventWorker
}
// Search in expressions
else if (ParameterMetadata::IsExpression(
"number", instrInfos.parameters[pNb].GetType()) ||
ParameterMetadata::IsExpression(
"string", instrInfos.parameters[pNb].GetType())) {
"number", instrInfos.parameters[pNb].GetType()) ||
ParameterMetadata::IsExpression(
"string", instrInfos.parameters[pNb].GetType())) {
auto node = instruction.GetParameter(pNb).GetRootNode();
IdentifierFinderExpressionNodeWorker searcher(
@@ -174,7 +177,7 @@ class GD_CORE_API IdentifierFinderEventWorker
}
// Remember the value of the last "object" parameter.
else if (gd::ParameterMetadata::IsObject(
instrInfos.parameters[pNb].GetType())) {
instrInfos.parameters[pNb].GetType())) {
lastObjectParameter =
instruction.GetParameter(pNb).GetPlainString();
}

View File

@@ -555,6 +555,22 @@ void EventsRefactorer::RemoveObjectInEvents(const gd::Platform& platform,
}
}
gd::String ReplaceAllOccurrencesCaseInsensitive(gd::String context,
const gd::String& from,
const gd::String& to) {
size_t lookHere = 0;
size_t foundHere;
size_t fromSize = from.size();
size_t toSize = to.size();
while ((foundHere = context.FindCaseInsensitive(from, lookHere)) !=
gd::String::npos) {
context.replace(foundHere, fromSize, to);
lookHere = foundHere + toSize;
}
return context;
}
std::vector<EventsSearchResult> EventsRefactorer::ReplaceStringInEvents(
gd::ObjectsContainer& project,
gd::ObjectsContainer& layout,
@@ -570,6 +586,32 @@ std::vector<EventsSearchResult> EventsRefactorer::ReplaceStringInEvents(
for (std::size_t i = 0; i < events.size(); ++i) {
bool eventModified = false;
std::vector<gd::Expression*> allObjectExpressions =
events[i].GetAllObjectExpressions();
for (std::size_t j = 0; j < allObjectExpressions.size(); ++j) {
gd::String newExpressionPlainString =
matchCase ? allObjectExpressions[j]->GetPlainString().FindAndReplace(
toReplace, newString, true)
: ReplaceAllOccurrencesCaseInsensitive(
allObjectExpressions[j]->GetPlainString(),
toReplace,
newString);
if (newExpressionPlainString !=
allObjectExpressions[j]->GetPlainString()) {
*allObjectExpressions[j] = gd::Expression(newExpressionPlainString);
if (!eventModified) {
modifiedEvents.push_back(EventsSearchResult(
std::weak_ptr<gd::BaseEvent>(events.GetEventSmartPtr(i)),
&events,
i));
eventModified = true;
}
}
}
if (inConditions) {
vector<gd::InstructionsList*> conditionsVectors =
events[i].GetAllConditionsVectors();
@@ -642,22 +684,6 @@ std::vector<EventsSearchResult> EventsRefactorer::ReplaceStringInEvents(
return modifiedEvents;
}
gd::String ReplaceAllOccurrencesCaseInsensitive(gd::String context,
gd::String from,
const gd::String& to) {
size_t lookHere = 0;
size_t foundHere;
size_t fromSize = from.size();
size_t toSize = to.size();
while ((foundHere = context.FindCaseInsensitive(from, lookHere)) !=
gd::String::npos) {
context.replace(foundHere, fromSize, to);
lookHere = foundHere + toSize;
}
return context;
}
bool EventsRefactorer::ReplaceStringInActions(gd::ObjectsContainer& project,
gd::ObjectsContainer& layout,
gd::InstructionsList& actions,
@@ -789,6 +815,24 @@ vector<EventsSearchResult> EventsRefactorer::SearchInEvents(
for (std::size_t i = 0; i < events.size(); ++i) {
bool eventAddedInResults = false;
std::vector<gd::Expression*> allObjectExpressions =
events[i].GetAllObjectExpressions();
for (std::size_t j = 0; j < allObjectExpressions.size(); ++j) {
size_t foundPosition =
matchCase
? allObjectExpressions[j]->GetPlainString().find(search)
: allObjectExpressions[j]->GetPlainString().FindCaseInsensitive(
search);
if (foundPosition != gd::String::npos && !eventAddedInResults) {
results.push_back(EventsSearchResult(
std::weak_ptr<gd::BaseEvent>(events.GetEventSmartPtr(i)),
&events,
i));
eventAddedInResults = true;
}
}
if (inConditions) {
vector<gd::InstructionsList*> conditionsVectors =
events[i].GetAllConditionsVectors();
@@ -803,6 +847,7 @@ vector<EventsSearchResult> EventsRefactorer::SearchInEvents(
std::weak_ptr<gd::BaseEvent>(events.GetEventSmartPtr(i)),
&events,
i));
eventAddedInResults = true;
}
}
}
@@ -820,6 +865,7 @@ vector<EventsSearchResult> EventsRefactorer::SearchInEvents(
std::weak_ptr<gd::BaseEvent>(events.GetEventSmartPtr(i)),
&events,
i));
eventAddedInResults = true;
}
}
}

View File

@@ -105,7 +105,7 @@ ExpressionValidator::Type ExpressionValidator::ValidateFunction(const gd::Functi
const gd::ObjectMetadata &objectMetadata =
MetadataProvider::GetObjectMetadata(platform, objectType);
if (objectMetadata.IsUnsupportedBaseObjectCapability(
if (!objectMetadata.IsSupportedBaseObjectCapability(
metadata.GetRequiredBaseObjectCapability())) {
RaiseTypeError(
_("This expression exists, but it can't be used on this object."),

View File

@@ -15,8 +15,8 @@ namespace gd {
void BehaviorObjectTypeRenamer::DoVisitEventBasedBehavior(
gd::EventsBasedBehavior &eventsBasedBehavior) {
if (eventsBasedBehavior.GetObjectType() == oldObjectType) {
eventsBasedBehavior.SetObjectType(newObjectType);
if (eventsBasedBehavior.GetObjectType().GetName() == oldObjectType) {
eventsBasedBehavior.GetObjectType().SetName(newObjectType);
}
}

View File

@@ -10,15 +10,17 @@
#include <map>
#include <memory>
#include <vector>
#include "GDCore/Extensions/Metadata/ParameterMetadataTools.h"
namespace gd {
void FunctionParameterObjectTypeRenamer::DoVisitEventsFunction(
gd::EventsFunction &eventsFunction) {
for (auto &&parameter : eventsFunction.GetParameters()) {
auto &objectType = parameter.GetValueTypeMetadata().GetObjectType();
if (gd::ParameterMetadata::IsObject(parameter.GetType()) &&
parameter.GetExtraInfo() == oldObjectType) {
parameter.SetExtraInfo(newObjectType);
objectType.GetName() == oldObjectType) {
objectType.SetName(newObjectType);
}
}
}

View File

@@ -13,6 +13,7 @@
#include "GDCore/Project/EventsBasedObject.h"
#include "GDCore/Project/EventsFunctionsExtension.h"
#include "GDCore/Project/EventsFunction.h"
#include "GDCore/Project/ObjectType.h"
#include "GDCore/Project/Project.h"
#include "GDCore/Project/PropertyDescriptor.h"
#include "GDCore/String.h"
@@ -32,14 +33,16 @@ void PropertyFunctionGenerator::GenerateObjectGetterAndSetter(
gd::Project &project, gd::EventsFunctionsExtension &extension,
gd::EventsBasedObject &eventsBasedObject,
const gd::NamedPropertyDescriptor &property) {
GenerateGetterAndSetter(project, extension, eventsBasedObject, property, "",
gd::ObjectType objectType;
objectType.SetName(gd::PlatformExtension::GetObjectFullType(extension.GetName(), eventsBasedObject.GetName()));
GenerateGetterAndSetter(project, extension, eventsBasedObject, property, objectType,
false, false);
}
void PropertyFunctionGenerator::GenerateGetterAndSetter(
gd::Project &project, gd::EventsFunctionsExtension &extension,
gd::AbstractEventsBasedEntity &eventsBasedEntity,
const gd::NamedPropertyDescriptor &property, const gd::String &objectType,
const gd::NamedPropertyDescriptor &property, const gd::ObjectType &objectType,
bool isBehavior, bool isSharedProperties) {
auto &propertyName = property.GetName();
auto &functionsContainer = eventsBasedEntity.GetEventsFunctions();
@@ -151,7 +154,8 @@ void PropertyFunctionGenerator::GenerateGetterAndSetter(
objectParameter.SetType("object")
.SetName("Object")
.SetDescription("Object")
.SetExtraInfo(objectType);
.GetValueTypeMetadata()
.SetObjectType(objectType);
if (!isBehavior) {
gd::String objectFullType = gd::PlatformExtension::GetObjectFullType(
extension.GetName(), eventsBasedEntity.GetName());

View File

@@ -16,6 +16,7 @@ class EventsBasedObject;
class AbstractEventsBasedEntity;
class PropertyDescriptor;
class NamedPropertyDescriptor;
class ObjectType;
} // namespace gd
namespace gd {
@@ -60,7 +61,7 @@ class GD_CORE_API PropertyFunctionGenerator {
gd::EventsFunctionsExtension &extension,
gd::AbstractEventsBasedEntity &eventsBasedEntity,
const gd::NamedPropertyDescriptor &property,
const gd::String &objectType,
const gd::ObjectType &objectType,
bool isBehavior,
bool isSharedProperties);

View File

@@ -102,7 +102,8 @@ void WholeProjectRefactorer::EnsureBehaviorEventsFunctionsProperParameters(
.SetType("object")
.SetName(behaviorObjectParameterName)
.SetDescription("Object")
.SetExtraInfo(eventsBasedBehavior.GetObjectType());
.GetValueTypeMetadata()
.SetObjectType(eventsBasedBehavior.GetObjectType());
parameters[1]
.SetType("behavior")
.SetName("Behavior")

View File

@@ -17,7 +17,7 @@ EventsBasedBehavior::EventsBasedBehavior()
void EventsBasedBehavior::SerializeTo(SerializerElement& element) const {
AbstractEventsBasedEntity::SerializeTo(element);
element.SetAttribute("objectType", objectType);
objectType.SerializeTo(element);
if (isPrivate) {
element.SetBoolAttribute("private", isPrivate);
}
@@ -28,7 +28,7 @@ void EventsBasedBehavior::SerializeTo(SerializerElement& element) const {
void EventsBasedBehavior::UnserializeFrom(gd::Project& project,
const SerializerElement& element) {
AbstractEventsBasedEntity::UnserializeFrom(project, element);
objectType = element.GetStringAttribute("objectType");
objectType.UnserializeFrom(element);
isPrivate = element.GetBoolAttribute("private");
sharedPropertyDescriptors.UnserializeElementsFrom(
"propertyDescriptor", element.GetChild("sharedPropertyDescriptors"));

View File

@@ -11,6 +11,7 @@
#include "GDCore/Project/NamedPropertyDescriptor.h"
#include "GDCore/Tools/SerializableWithNameList.h"
#include "GDCore/Project/EventsFunctionsContainer.h"
#include "GDCore/Project/ObjectType.h"
#include "GDCore/String.h"
namespace gd {
class SerializerElement;
@@ -63,21 +64,18 @@ class GD_CORE_API EventsBasedBehavior: public AbstractEventsBasedEntity {
/**
* \brief Get the object type the behavior should be used with.
*/
const gd::String& GetObjectType() const { return objectType; };
gd::ObjectType& GetObjectType() { return objectType; };
/**
* \brief Set the object type the behavior should be used with.
* \brief Get the object type the behavior should be used with.
*/
EventsBasedBehavior& SetObjectType(const gd::String& objectType_) {
objectType = objectType_;
return *this;
}
const gd::ObjectType& GetObjectType() const { return objectType; };
/**
* \brief Check if the behavior is private - it can't be used outside of its
* extension.
*/
bool IsPrivate() { return isPrivate; }
bool IsPrivate() const { return isPrivate; }
/**
* \brief Set that the behavior is private - it can't be used outside of its
@@ -138,7 +136,7 @@ class GD_CORE_API EventsBasedBehavior: public AbstractEventsBasedEntity {
const SerializerElement& element) override;
private:
gd::String objectType;
gd::ObjectType objectType;
bool isPrivate = false;
SerializableWithNameList<NamedPropertyDescriptor> sharedPropertyDescriptors;
};

View File

@@ -201,7 +201,7 @@ class GD_CORE_API EventsFunction {
/**
* \brief Returns true if the function is private.
*/
bool IsPrivate() { return isPrivate; }
bool IsPrivate() const { return isPrivate; }
/**
* \brief Sets the privateness of the function.

View File

@@ -207,6 +207,13 @@ class GD_CORE_API EventsFunctionsExtension : public EventsFunctionsContainer {
return dependencies;
};
/**
* \brief Returns the list of dependencies.
*/
const std::vector<gd::DependencyMetadata>& GetAllDependencies() const {
return dependencies;
};
///@}
/** \name Serialization

View File

@@ -0,0 +1,88 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#include "ObjectType.h"
#include "EventsFunctionsContainer.h"
#include "GDCore/Serialization/SerializerElement.h"
#include "GDCore/Tools/MakeUnique.h"
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
#include "GDCore/Extensions/Metadata/ObjectMetadata.h"
#include "GDCore/Project/Layout.h"
#include "GDCore/Extensions/Platform.h"
namespace gd {
ObjectType::ObjectType() {}
bool ObjectType::HasCapability(const gd::String& name) const {
return std::find(capabilities.begin(), capabilities.end(), name) !=
capabilities.end();
}
ObjectType& ObjectType::AddCapability(const gd::String& name) {
if (!HasCapability(name)) capabilities.push_back(name);
return *this;
}
void ObjectType::RemoveCapability(const gd::String& name) {
capabilities.erase(
std::remove(capabilities.begin(), capabilities.end(), name),
capabilities.end());
}
void ObjectType::SerializeTo(SerializerElement& element) const {
element.SetAttribute("objectType", name);
SerializerElement& capabilitiesElement = element.AddChild("capabilities");
capabilitiesElement.ConsiderAsArrayOf("object");
for (auto& name : capabilities) {
capabilitiesElement.AddChild("capability").SetAttribute("name", name);
}
}
void ObjectType::UnserializeFrom(const SerializerElement& element) {
name = element.GetStringAttribute("objectType");
SerializerElement& capabilitiesElement = element.GetChild("capabilities");
capabilitiesElement.ConsiderAsArrayOf("capability");
for (std::size_t j = 0; j < capabilitiesElement.GetChildrenCount(); ++j)
AddCapability(capabilitiesElement.GetChild(j).GetStringAttribute("name"));
}
bool ObjectType::IsMatchedBy(
const gd::Platform& platform,
const ObjectsContainer& globalObjectsContainer,
const ObjectsContainer& objectsContainer,
const gd::String& objectName) {
gd::String objectType = gd::GetTypeOfObject(
globalObjectsContainer,
objectsContainer,
objectName,
false);
if (!IsBaseObject() && name != objectType) {
return false;
}
if (capabilities.empty()) {
return true;
}
// TODO Handle groups
auto& objectMetadata = gd::MetadataProvider::GetObjectMetadata(
platform,
objectType
);
for (auto& capability : capabilities) {
if (!objectMetadata.IsSupportedBaseObjectCapability(capability)) {
return false;
}
}
return true;
}
} // namespace gd

View File

@@ -0,0 +1,73 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#pragma once
#include "GDCore/String.h"
#include <vector>
namespace gd {
class SerializerElement;
class Platform;
class ObjectsContainer;
} // namespace gd
namespace gd {
/**
* \brief
*
* \ingroup PlatformDefinition
*/
class GD_CORE_API ObjectType {
public:
ObjectType();
virtual ~ObjectType(){};
/**
* \brief Get the object type the behavior should be used with.
*/
const gd::String &GetName() const { return name; };
/**
* \brief Set the object type the behavior should be used with.
*/
ObjectType &SetName(const gd::String &name_) {
name = name_;
return *this;
}
bool IsBaseObject() const { return name.empty(); }
bool IsMatchedBy(const gd::Platform &platform,
const ObjectsContainer &globalObjectsContainer,
const ObjectsContainer &objectsContainer,
const gd::String &objectName);
/**
* \brief Return true if an object is found inside the ObjectGroup.
*/
bool HasCapability(const gd::String &name) const;
/**
* \brief Add an object name to the group.
*/
ObjectType &AddCapability(const gd::String &name);
/**
* \brief Remove an object name from the group
*/
void RemoveCapability(const gd::String &name);
void SerializeTo(SerializerElement &element) const;
void UnserializeFrom(const SerializerElement &element);
private:
gd::String name;
std::vector<gd::String> capabilities;
};
} // namespace gd

View File

@@ -686,6 +686,16 @@ String GD_CORE_API operator+(const char *lhs, const String &rhs)
return str;
}
const String& GD_CORE_API operator||(const String& lhs, const String &rhs)
{
return lhs.empty() ? rhs : lhs;
}
String GD_CORE_API operator||(String lhs, const char *rhs)
{
return lhs.empty() ? rhs : lhs;
}
bool GD_CORE_API operator==( const String &lhs, const String &rhs )
{
return (lhs.compare(rhs) == 0);

View File

@@ -699,6 +699,10 @@ String GD_CORE_API operator+(String lhs, const char *rhs);
*/
String GD_CORE_API operator+(const char *lhs, const String &rhs);
const String& GD_CORE_API operator||(const String &lhs, const String &rhs);
String GD_CORE_API operator||(String lhs, const char *rhs);
/**
* \}
*/

View File

@@ -37,7 +37,7 @@ void AddEventsBasedExtension(gd::Project &project) {
"MyEventsBasedBehavior", 0);
eventsBasedBehavior.SetFullName("My events based behavior");
eventsBasedBehavior.SetDescription("An events based behavior for test");
eventsBasedBehavior.SetObjectType("");
eventsBasedBehavior.GetObjectType().SetName("");
eventsBasedBehavior.GetPropertyDescriptors()
.InsertNew("MyProperty", 0)
.SetType("Number");

View File

@@ -122,7 +122,7 @@ void SetupProjectWithDummyPlatform(gd::Project& project,
"")
.AddParameter("object", _("Object"), "")
.AddParameter("expression", _("Number parameter"))
.SetRequiresBaseObjectCapability("effect")
.SetRequiredBaseObjectCapability("effect")
.SetFunctionName("getSomethingRequiringEffectCapability");
baseObject
.AddExpression("GetFromBaseExpression",
@@ -403,7 +403,8 @@ void SetupProjectWithDummyPlatform(gd::Project& project,
"FakeObjectWithUnsupportedCapability",
"This is FakeObjectWithUnsupportedCapability",
"")
.AddUnsupportedBaseObjectCapability("effect");
.MarkBaseObjectCapabilityAsUnsupported("effect")
.MarkBaseObjectCapabilityAsSupported("resizable");
}
// Actions and expressions with several parameter types.

View File

@@ -26,7 +26,7 @@ CreateBehavior(gd::EventsFunctionsExtension &eventsExtension) {
"MyEventsBasedBehavior", 0);
eventsBasedBehavior.SetFullName("My events based behavior");
eventsBasedBehavior.SetDescription("An events based behavior for test");
eventsBasedBehavior.SetObjectType("");
eventsBasedBehavior.GetObjectType().SetName("");
return eventsBasedBehavior;
};
@@ -486,8 +486,9 @@ TEST_CASE("PropertyFunctionGenerator", "[common]") {
auto &objectParameter = setter.GetParameters().at(0);
REQUIRE(objectParameter.GetName() == "Object");
REQUIRE(objectParameter.GetType() == "object");
REQUIRE(objectParameter.GetExtraInfo() ==
"MyEventsExtension::MyEventsBasedObject");
REQUIRE(
objectParameter.GetValueTypeMetadata().GetObjectType().GetName() ==
"MyEventsExtension::MyEventsBasedObject");
auto &valueParameter = setter.GetParameters().at(1);
REQUIRE(valueParameter.GetName() == "Value");
REQUIRE(valueParameter.GetType() == "yesorno");

View File

@@ -76,6 +76,12 @@ const gd::String &GetEventFirstActionType(const gd::BaseEvent &event) {
return actions.Get(0).GetType();
}
gd::ParameterMetadata &SetObjectType(gd::ParameterMetadata &objectParameter,
const gd::String type) {
objectParameter.GetValueTypeMetadata().GetObjectType().SetName(type);
return objectParameter;
}
enum TestEvent {
FreeFunctionAction,
FreeFunctionWithExpression,
@@ -860,27 +866,25 @@ SetupProjectWithEventsFunctionExtension(gd::Project &project) {
"MyEventsBasedBehavior", 0);
eventsBasedBehavior.SetFullName("My events based behavior");
eventsBasedBehavior.SetDescription("An events based behavior for test");
eventsBasedBehavior.SetObjectType("MyEventsExtension::MyEventsBasedObject");
eventsBasedBehavior.GetObjectType().SetName("MyEventsExtension::MyEventsBasedObject");
// Add functions, and parameters that should be there by convention.
auto &behaviorEventsFunctions = eventsBasedBehavior.GetEventsFunctions();
auto &behaviorAction = behaviorEventsFunctions.InsertNewEventsFunction(
"MyBehaviorEventsFunction", 0);
behaviorAction.GetParameters().push_back(
gd::ParameterMetadata()
.SetName("Object")
.SetType("object")
.SetExtraInfo("MyEventsExtension::MyEventsBasedObject"));
behaviorAction.GetParameters().push_back(SetObjectType(
gd::ParameterMetadata().SetName("Object").SetType("object"),
"MyEventsExtension::MyEventsBasedObject"));
behaviorAction.GetParameters().push_back(
gd::ParameterMetadata()
.SetName("Behavior")
.SetType("behavior")
.SetExtraInfo("MyEventsExtension::MyEventsBasedBehavior"));
behaviorAction.GetParameters().push_back(
gd::ParameterMetadata()
.SetName("ObjectWithMyBehavior")
.SetType("object")
.SetExtraInfo("MyEventsExtension::MyEventsBasedObject"));
SetObjectType(gd::ParameterMetadata()
.SetName("ObjectWithMyBehavior")
.SetType("object"),
"MyEventsExtension::MyEventsBasedObject"));
behaviorAction.GetParameters().push_back(
gd::ParameterMetadata()
.SetName("OtherBehavior")
@@ -893,11 +897,9 @@ SetupProjectWithEventsFunctionExtension(gd::Project &project) {
behaviorEventsFunctions
.InsertNewEventsFunction("MyBehaviorEventsFunctionExpression", 1)
.SetFunctionType(gd::EventsFunction::Expression);
behaviorExpression.GetParameters().push_back(
gd::ParameterMetadata()
.SetName("Object")
.SetType("object")
.SetExtraInfo("MyEventsExtension::MyEventsBasedObject"));
behaviorExpression.GetParameters().push_back(SetObjectType(
gd::ParameterMetadata().SetName("Object").SetType("object"),
"MyEventsExtension::MyEventsBasedObject"));
behaviorExpression.GetParameters().push_back(
gd::ParameterMetadata()
.SetName("Behavior")
@@ -951,16 +953,12 @@ SetupProjectWithEventsFunctionExtension(gd::Project &project) {
auto &objectEventsFunctions = eventsBasedObject.GetEventsFunctions();
auto &objectAction = objectEventsFunctions.InsertNewEventsFunction(
"MyObjectEventsFunction", 0);
objectAction.GetParameters().push_back(
gd::ParameterMetadata()
.SetName("Object")
.SetType("object")
.SetExtraInfo("MyEventsExtension::MyEventsBasedObject"));
objectAction.GetParameters().push_back(
gd::ParameterMetadata()
.SetName("OtherObject")
.SetType("object")
.SetExtraInfo("MyEventsExtension::MyEventsBasedObject"));
objectAction.GetParameters().push_back(SetObjectType(
gd::ParameterMetadata().SetName("Object").SetType("object"),
"MyEventsExtension::MyEventsBasedObject"));
objectAction.GetParameters().push_back(SetObjectType(
gd::ParameterMetadata().SetName("OtherObject").SetType("object"),
"MyEventsExtension::MyEventsBasedObject"));
objectAction.GetParameters().push_back(
gd::ParameterMetadata()
.SetName("OtherBehavior")
@@ -971,11 +969,9 @@ SetupProjectWithEventsFunctionExtension(gd::Project &project) {
objectEventsFunctions
.InsertNewEventsFunction("MyObjectEventsFunctionExpression", 1)
.SetFunctionType(gd::EventsFunction::Expression);
objectExpression.GetParameters().push_back(
gd::ParameterMetadata()
.SetName("Object")
.SetType("object")
.SetExtraInfo("MyEventsExtension::MyEventsBasedObject"));
objectExpression.GetParameters().push_back(SetObjectType(
gd::ParameterMetadata().SetName("Object").SetType("object"),
"MyEventsExtension::MyEventsBasedObject"));
auto &objectExpressionAndCondition =
objectEventsFunctions
@@ -1011,17 +1007,15 @@ SetupProjectWithEventsFunctionExtension(gd::Project &project) {
"MyOtherEventsBasedBehavior", 0);
eventsBasedBehavior.SetFullName("My events based behavior");
eventsBasedBehavior.SetDescription("An events based behavior for test");
eventsBasedBehavior.SetObjectType("MyEventsExtension::MyEventsBasedObject");
eventsBasedBehavior.GetObjectType().SetName("MyEventsExtension::MyEventsBasedObject");
// Add functions, and parameters that should be there by convention.
auto &behaviorEventsFunctions = eventsBasedBehavior.GetEventsFunctions();
auto &behaviorAction = behaviorEventsFunctions.InsertNewEventsFunction(
"MyBehaviorEventsFunction", 0);
behaviorAction.GetParameters().push_back(
gd::ParameterMetadata()
.SetName("Object")
.SetType("object")
.SetExtraInfo("MyEventsExtension::MyEventsBasedObject"));
behaviorAction.GetParameters().push_back(SetObjectType(
gd::ParameterMetadata().SetName("Object").SetType("object"),
"MyEventsExtension::MyEventsBasedObject"));
behaviorAction.GetParameters().push_back(
gd::ParameterMetadata()
.SetName("Behavior")
@@ -1029,20 +1023,18 @@ SetupProjectWithEventsFunctionExtension(gd::Project &project) {
.SetExtraInfo("MyEventsExtension::MyEventsBasedBehavior"));
// Define the same objects as in the layout to be consistent with events.
behaviorAction.GetParameters().push_back(
gd::ParameterMetadata()
.SetName("ObjectWithMyBehavior")
.SetType("object")
.SetExtraInfo("MyExtension::Sprite"));
SetObjectType(gd::ParameterMetadata()
.SetName("ObjectWithMyBehavior")
.SetType("object"),
"MyExtension::Sprite"));
behaviorAction.GetParameters().push_back(
gd::ParameterMetadata()
.SetName("MyBehavior")
.SetType("behavior")
.SetExtraInfo("MyEventsExtension::MyEventsBasedBehavior"));
behaviorAction.GetParameters().push_back(
gd::ParameterMetadata()
.SetName("MyCustomObject")
.SetType("object")
.SetExtraInfo("MyEventsExtension::MyEventsBasedObject"));
behaviorAction.GetParameters().push_back(SetObjectType(
gd::ParameterMetadata().SetName("MyCustomObject").SetType("object"),
"MyEventsExtension::MyEventsBasedObject"));
}
// Add an other events based object that uses previously defined events based
@@ -1057,11 +1049,9 @@ SetupProjectWithEventsFunctionExtension(gd::Project &project) {
auto &objectEventsFunctions = eventsBasedObject.GetEventsFunctions();
auto &objectAction = objectEventsFunctions.InsertNewEventsFunction(
"MyObjectEventsFunction", 0);
objectAction.GetParameters().push_back(
gd::ParameterMetadata()
.SetName("Object")
.SetType("object")
.SetExtraInfo("MyEventsExtension::MyOtherEventsBasedObject"));
objectAction.GetParameters().push_back(SetObjectType(
gd::ParameterMetadata().SetName("Object").SetType("object"),
"MyEventsExtension::MyOtherEventsBasedObject"));
// Add a child-object with the same names the one from the scene
// to be able to use the same events list.
@@ -1083,11 +1073,9 @@ SetupProjectWithEventsFunctionExtension(gd::Project &project) {
.SetName("currentScene")
.SetType("")
.SetCodeOnly(true));
action.GetParameters().push_back(
gd::ParameterMetadata()
.SetName("Object")
.SetType("object")
.SetExtraInfo("MyEventsExtension::MyEventsBasedObject"));
action.GetParameters().push_back(SetObjectType(
gd::ParameterMetadata().SetName("Object").SetType("object"),
"MyEventsExtension::MyEventsBasedObject"));
action.GetParameters().push_back(
gd::ParameterMetadata()
.SetName("Behavior")
@@ -1126,20 +1114,20 @@ SetupProjectWithEventsFunctionExtension(gd::Project &project) {
eventsExtension.InsertNewEventsFunction("MyOtherEventsFunction", 0);
// Define the same objects as in the layout to be consistent with events.
action.GetParameters().push_back(
gd::ParameterMetadata()
SetObjectType(gd::ParameterMetadata()
.SetName("ObjectWithMyBehavior")
.SetType("object")
.SetExtraInfo("MyExtension::Sprite"));
.SetType("object"),
"MyExtension::Sprite"));
action.GetParameters().push_back(
gd::ParameterMetadata()
.SetName("MyBehavior")
.SetType("behavior")
.SetExtraInfo("MyEventsExtension::MyEventsBasedBehavior"));
action.GetParameters().push_back(
gd::ParameterMetadata()
SetObjectType(gd::ParameterMetadata()
.SetName("MyCustomObject")
.SetType("object")
.SetExtraInfo("MyEventsExtension::MyEventsBasedObject"));
.SetType("object"),
"MyEventsExtension::MyEventsBasedObject"));
auto &group = action.GetObjectGroups().InsertNew("GroupWithMyBehavior");
group.AddObject("ObjectWithMyBehavior");
}
@@ -1839,7 +1827,7 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
"MyOtherEventsBasedBehavior", 0);
copiedBehavior.SetFullName("My events based behavior");
copiedBehavior.SetDescription("An events based behavior for test");
copiedBehavior.SetObjectType("MyEventsExtension::MyEventsBasedObject");
copiedBehavior.GetObjectType().SetName("MyEventsExtension::MyEventsBasedObject");
// Add the copied events.
auto &behaviorEventsFunctions = copiedBehavior.GetEventsFunctions();
@@ -1876,8 +1864,11 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
auto &myEventsFunction =
project.GetEventsFunctionsExtension("MyEventsExtension")
.GetEventsFunction("MyEventsFunction");
REQUIRE(myEventsFunction.GetParameters().at(1).GetExtraInfo() ==
"MyRenamedExtension::MyEventsBasedObject");
REQUIRE(myEventsFunction.GetParameters()
.at(1)
.GetValueTypeMetadata()
.GetObjectType()
.GetName() == "MyRenamedExtension::MyEventsBasedObject");
REQUIRE(myEventsFunction.GetParameters().at(2).GetExtraInfo() ==
"MyRenamedExtension::MyEventsBasedBehavior");
@@ -1889,8 +1880,11 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
.Get("MyEventsBasedBehavior")
.GetEventsFunctions()
.GetEventsFunction("MyBehaviorEventsFunction");
REQUIRE(myBehaviorEventsFunction.GetParameters().at(2).GetExtraInfo() ==
"MyRenamedExtension::MyEventsBasedObject");
REQUIRE(myBehaviorEventsFunction.GetParameters()
.at(2)
.GetValueTypeMetadata()
.GetObjectType()
.GetName() == "MyRenamedExtension::MyEventsBasedObject");
REQUIRE(myBehaviorEventsFunction.GetParameters().at(3).GetExtraInfo() ==
"MyRenamedExtension::MyEventsBasedBehavior");
}
@@ -1903,8 +1897,11 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
.Get("MyEventsBasedObject")
.GetEventsFunctions()
.GetEventsFunction("MyObjectEventsFunction");
REQUIRE(myBehaviorEventsFunction.GetParameters().at(1).GetExtraInfo() ==
"MyRenamedExtension::MyEventsBasedObject");
REQUIRE(myBehaviorEventsFunction.GetParameters()
.at(1)
.GetValueTypeMetadata()
.GetObjectType()
.GetName() == "MyRenamedExtension::MyEventsBasedObject");
REQUIRE(myBehaviorEventsFunction.GetParameters().at(2).GetExtraInfo() ==
"MyRenamedExtension::MyEventsBasedBehavior");
}
@@ -1922,7 +1919,8 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
REQUIRE(project.GetEventsFunctionsExtension("MyEventsExtension")
.GetEventsBasedBehaviors()
.Get("MyEventsBasedBehavior")
.GetObjectType() == "MyRenamedExtension::MyEventsBasedObject");
.GetObjectType()
.GetName() == "MyRenamedExtension::MyEventsBasedObject");
}
SECTION("(Free) events action renamed") {
@@ -2247,8 +2245,11 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
auto &myEventsFunction =
project.GetEventsFunctionsExtension("MyEventsExtension")
.GetEventsFunction("MyEventsFunction");
REQUIRE(myEventsFunction.GetParameters().at(1).GetExtraInfo() ==
"MyEventsExtension::MyRenamedEventsBasedObject");
REQUIRE(myEventsFunction.GetParameters()
.at(1)
.GetValueTypeMetadata()
.GetObjectType()
.GetName() == "MyEventsExtension::MyRenamedEventsBasedObject");
// Behavior function
{
@@ -2258,7 +2259,11 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
.Get("MyEventsBasedBehavior")
.GetEventsFunctions()
.GetEventsFunction("MyBehaviorEventsFunction");
REQUIRE(myBehaviorEventsFunction.GetParameters().at(2).GetExtraInfo() ==
REQUIRE(myBehaviorEventsFunction.GetParameters()
.at(2)
.GetValueTypeMetadata()
.GetObjectType()
.GetName() ==
"MyEventsExtension::MyRenamedEventsBasedObject");
}
@@ -2270,7 +2275,11 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
.Get("MyEventsBasedObject")
.GetEventsFunctions()
.GetEventsFunction("MyObjectEventsFunction");
REQUIRE(myBehaviorEventsFunction.GetParameters().at(1).GetExtraInfo() ==
REQUIRE(myBehaviorEventsFunction.GetParameters()
.at(1)
.GetValueTypeMetadata()
.GetObjectType()
.GetName() ==
"MyEventsExtension::MyRenamedEventsBasedObject");
}
}
@@ -2290,8 +2299,8 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
REQUIRE(project.GetEventsFunctionsExtension("MyEventsExtension")
.GetEventsBasedBehaviors()
.Get("MyEventsBasedBehavior")
.GetObjectType() ==
"MyEventsExtension::MyRenamedEventsBasedObject");
.GetObjectType()
.GetName() == "MyEventsExtension::MyRenamedEventsBasedObject");
}
// TODO: Check that this works when behaviors are attached to a child-object.
SECTION("Events based behavior renamed (other behaviors properties update)") {

View File

@@ -0,0 +1 @@

View File

@@ -48,7 +48,11 @@ module.exports = {
new gd.Model3DObjectConfiguration()
)
.setCategoryFullName(_('3D'))
.addUnsupportedBaseObjectCapability('effect')
.markBaseObjectCapabilityAsUnsupported('effect')
.markBaseObjectCapabilityAsSupported('resizable')
.markBaseObjectCapabilityAsSupported('scalable')
.markBaseObjectCapabilityAsSupported('flippable')
.markBaseObjectCapabilityAsSupported('animable')
.setIncludeFile('Extensions/3D/A_RuntimeObject3D.js')
.addIncludeFile('Extensions/3D/A_RuntimeObject3DRenderer.js')
.addIncludeFile('Extensions/3D/Model3DRuntimeObject.js')
@@ -85,6 +89,7 @@ module.exports = {
.setFunctionName('setDepth')
.setGetter('getDepth');
// Deprecated
object
.addScopedAction(
'SetWidth',
@@ -100,10 +105,12 @@ module.exports = {
'number',
gd.ParameterOptions.makeNewOptions()
)
.setHidden()
.markAsAdvanced()
.setFunctionName('setWidth')
.setGetter('getWidth');
// Deprecated
object
.addScopedCondition(
'Width',
@@ -119,9 +126,11 @@ module.exports = {
'number',
gd.ParameterOptions.makeNewOptions()
)
.setHidden()
.markAsAdvanced()
.setFunctionName('getWidth');
// Deprecated
object
.addScopedAction(
'SetHeight',
@@ -137,10 +146,12 @@ module.exports = {
'number',
gd.ParameterOptions.makeNewOptions()
)
.setHidden()
.markAsAdvanced()
.setFunctionName('setHeight')
.setGetter('getHeight');
// Deprecated
object
.addScopedCondition(
'Height',
@@ -156,9 +167,11 @@ module.exports = {
'number',
gd.ParameterOptions.makeNewOptions()
)
.setHidden()
.markAsAdvanced()
.setFunctionName('getHeight');
// Deprecated
object
.addExpressionAndConditionAndAction(
'number',
@@ -171,9 +184,11 @@ module.exports = {
)
.addParameter('object', _('3D model'), 'Model3DObject', false)
.useStandardParameters('number', gd.ParameterOptions.makeNewOptions())
.setHidden()
.setFunctionName('setHeight')
.setGetter('getHeight');
// Deprecated
object
.addScopedAction(
'Scale',
@@ -191,10 +206,12 @@ module.exports = {
_('Scale (1 by default)')
)
)
.setHidden()
.markAsAdvanced()
.setFunctionName('setScale')
.setGetter('getScale');
// Deprecated
object
.addExpressionAndConditionAndAction(
'number',
@@ -212,10 +229,12 @@ module.exports = {
_('Scale (1 by default)')
)
)
.setHidden()
.markAsAdvanced()
.setFunctionName('setScaleX')
.setGetter('getScaleX');
// Deprecated
object
.addExpressionAndConditionAndAction(
'number',
@@ -233,6 +252,7 @@ module.exports = {
_('Scale (1 by default)')
)
)
.setHidden()
.markAsAdvanced()
.setFunctionName('setScaleY')
.setGetter('getScaleY');
@@ -258,6 +278,7 @@ module.exports = {
.setFunctionName('setScaleZ')
.setGetter('getScaleZ');
// Deprecated
object
.addScopedAction(
'FlipX',
@@ -270,9 +291,11 @@ module.exports = {
)
.addParameter('object', _('3D model'), 'Model3DObject')
.addParameter('yesorno', _('Activate flipping'))
.setHidden()
.markAsSimple()
.setFunctionName('flipX');
// Deprecated
object
.addScopedAction(
'FlipY',
@@ -285,6 +308,7 @@ module.exports = {
)
.addParameter('object', _('3D model'), 'Model3DObject')
.addParameter('yesorno', _('Activate flipping'))
.setHidden()
.markAsSimple()
.setFunctionName('flipY');
@@ -303,6 +327,7 @@ module.exports = {
.markAsSimple()
.setFunctionName('flipZ');
// Deprecated
object
.addScopedCondition(
'FlippedX',
@@ -314,8 +339,10 @@ module.exports = {
'res/actions/flipX.png'
)
.addParameter('object', _('3D model'), 'Model3DObject')
.setHidden()
.setFunctionName('isFlippedX');
// Deprecated
object
.addScopedCondition(
'FlippedY',
@@ -327,6 +354,7 @@ module.exports = {
'res/actions/flipY.png'
)
.addParameter('object', _('3D model'), 'Model3DObject')
.setHidden()
.setFunctionName('isFlippedY');
object
@@ -438,6 +466,7 @@ module.exports = {
.addParameter('object', _('3D model'), 'Model3DObject')
.useStandardParameters('number', gd.ParameterOptions.makeNewOptions())
.markAsSimple()
.setHidden()
.setFunctionName('setAnimationIndex')
.setGetter('getAnimationIndex');
@@ -459,6 +488,7 @@ module.exports = {
)
)
.markAsAdvanced()
.setHidden()
.setFunctionName('setAnimationName')
.setGetter('getAnimationName');
@@ -474,6 +504,7 @@ module.exports = {
)
.addParameter('object', _('3D model'), 'Model3DObject')
.markAsSimple()
.setHidden()
.setFunctionName('pauseAnimation');
object
@@ -488,6 +519,7 @@ module.exports = {
)
.addParameter('object', _('3D model'), 'Model3DObject')
.markAsSimple()
.setHidden()
.setFunctionName('resumeAnimation');
object
@@ -508,6 +540,7 @@ module.exports = {
gd.ParameterOptions.makeNewOptions().setDescription(_('Speed scale'))
)
.markAsSimple()
.setHidden()
.setFunctionName('setAnimationSpeedScale')
.setGetter('getAnimationSpeedScale');
@@ -523,6 +556,7 @@ module.exports = {
)
.addParameter('object', _('3D model'), 'Model3DObject')
.markAsSimple()
.setHidden()
.setFunctionName('isAnimationPaused');
object
@@ -539,6 +573,7 @@ module.exports = {
)
.addParameter('object', _('3D model'), 'Model3DObject')
.markAsSimple()
.setHidden()
.setFunctionName('hasAnimationEnded');
}
@@ -864,7 +899,10 @@ module.exports = {
Cube3DObject
)
.setCategoryFullName(_('3D'))
.addUnsupportedBaseObjectCapability('effect')
.markBaseObjectCapabilityAsUnsupported('effect')
.markBaseObjectCapabilityAsSupported('resizable')
.markBaseObjectCapabilityAsSupported('scalable')
.markBaseObjectCapabilityAsSupported('flippable')
.setIncludeFile('Extensions/3D/A_RuntimeObject3D.js')
.addIncludeFile('Extensions/3D/A_RuntimeObject3DRenderer.js')
.addIncludeFile('Extensions/3D/Cube3DRuntimeObject.js')
@@ -901,6 +939,7 @@ module.exports = {
.setFunctionName('setDepth')
.setGetter('getDepth');
// Deprecated
object
.addScopedAction(
'SetWidth',
@@ -916,10 +955,12 @@ module.exports = {
'number',
gd.ParameterOptions.makeNewOptions()
)
.setHidden()
.markAsAdvanced()
.setFunctionName('setWidth')
.setGetter('getWidth');
// Deprecated
object
.addScopedCondition(
'Width',
@@ -935,9 +976,11 @@ module.exports = {
'number',
gd.ParameterOptions.makeNewOptions()
)
.setHidden()
.markAsAdvanced()
.setFunctionName('getWidth');
// Deprecated
object
.addScopedAction(
'SetHeight',
@@ -953,10 +996,12 @@ module.exports = {
'number',
gd.ParameterOptions.makeNewOptions()
)
.setHidden()
.markAsAdvanced()
.setFunctionName('setHeight')
.setGetter('getHeight');
// Deprecated
object
.addScopedCondition(
'Height',
@@ -972,9 +1017,11 @@ module.exports = {
'number',
gd.ParameterOptions.makeNewOptions()
)
.setHidden()
.markAsAdvanced()
.setFunctionName('getHeight');
// Deprecated
object
.addScopedAction(
'Scale',
@@ -992,10 +1039,12 @@ module.exports = {
_('Scale (1 by default)')
)
)
.setHidden()
.markAsAdvanced()
.setFunctionName('setScale')
.setGetter('getScale');
// Deprecated
object
.addExpressionAndConditionAndAction(
'number',
@@ -1013,10 +1062,12 @@ module.exports = {
_('Scale (1 by default)')
)
)
.setHidden()
.markAsAdvanced()
.setFunctionName('setScaleX')
.setGetter('getScaleX');
// Deprecated
object
.addExpressionAndConditionAndAction(
'number',
@@ -1034,6 +1085,7 @@ module.exports = {
_('Scale (1 by default)')
)
)
.setHidden()
.markAsAdvanced()
.setFunctionName('setScaleY')
.setGetter('getScaleY');
@@ -1059,6 +1111,7 @@ module.exports = {
.setFunctionName('setScaleZ')
.setGetter('getScaleZ');
// Deprecated
object
.addScopedAction(
'FlipX',
@@ -1072,8 +1125,10 @@ module.exports = {
.addParameter('object', _('3D cube'), 'Cube3DObject')
.addParameter('yesorno', _('Activate flipping'))
.markAsSimple()
.setHidden()
.setFunctionName('flipX');
// Deprecated
object
.addScopedAction(
'FlipY',
@@ -1087,6 +1142,7 @@ module.exports = {
.addParameter('object', _('3D cube'), 'Cube3DObject')
.addParameter('yesorno', _('Activate flipping'))
.markAsSimple()
.setHidden()
.setFunctionName('flipY');
object
@@ -1104,6 +1160,7 @@ module.exports = {
.markAsSimple()
.setFunctionName('flipZ');
// Deprecated
object
.addScopedCondition(
'FlippedX',
@@ -1115,8 +1172,10 @@ module.exports = {
'res/actions/flipX.png'
)
.addParameter('object', _('3D cube'), 'Cube3DObject')
.setHidden()
.setFunctionName('isFlippedX');
// Deprecated
object
.addScopedCondition(
'FlippedY',
@@ -1128,6 +1187,7 @@ module.exports = {
'res/actions/flipY.png'
)
.addParameter('object', _('3D cube'), 'Cube3DObject')
.setHidden()
.setFunctionName('isFlippedY');
object

View File

@@ -1,20 +1,23 @@
cmake_minimum_required(VERSION 2.6)
cmake_policy(SET CMP0015 NEW)
cmake_minimum_required(VERSION 3.5)
project(AnchorBehavior)
gd_add_extension_includes()
#Defines
###
# Defines
#
gd_add_extension_definitions(AnchorBehavior)
#The targets
###
# The targets
#
include_directories(.)
file(GLOB source_files *.cpp *.h)
file(
GLOB
source_files
*.cpp
*.h)
gd_add_clang_utils(AnchorBehavior "${source_files}")
gd_add_extension_target(AnchorBehavior "${source_files}")
#Linker files for the IDE extension
###
# Linker files for the IDE extension
#
gd_extension_link_libraries(AnchorBehavior)

View File

@@ -1,28 +1,34 @@
#This is the CMake file used to build the C++ extensions.
#For more information, see the README.md file.
# This is the CMake file used to build the C++ extensions.
# For more information, see the README.md file.
cmake_minimum_required(VERSION 2.6)
cmake_policy(SET CMP0011 NEW)
cmake_minimum_required(VERSION 3.5)
project(GD-Extensions)
include(CMakeUtils.txt) #Functions to factor common tasks done in CMakeLists.txt of extensions
include(CMakeUtils.txt) # Functions to factor common tasks done in CMakeLists.txt of extensions
#Add all the CMakeLists (for non pure JS extensions):
ADD_SUBDIRECTORY(3D)
ADD_SUBDIRECTORY(AnchorBehavior)
ADD_SUBDIRECTORY(DestroyOutsideBehavior)
ADD_SUBDIRECTORY(DraggableBehavior)
ADD_SUBDIRECTORY(Inventory)
ADD_SUBDIRECTORY(LinkedObjects)
ADD_SUBDIRECTORY(ParticleSystem)
ADD_SUBDIRECTORY(PanelSpriteObject)
ADD_SUBDIRECTORY(PathfindingBehavior)
ADD_SUBDIRECTORY(PhysicsBehavior)
ADD_SUBDIRECTORY(PlatformBehavior)
ADD_SUBDIRECTORY(PrimitiveDrawing)
ADD_SUBDIRECTORY(Shopify)
ADD_SUBDIRECTORY(SystemInfo)
ADD_SUBDIRECTORY(TextEntryObject)
ADD_SUBDIRECTORY(TextObject)
ADD_SUBDIRECTORY(TiledSpriteObject)
ADD_SUBDIRECTORY(TopDownMovementBehavior)
# List of non pure JS extensions
set(
GD_EXTENSIONS
3D
AnchorBehavior
DestroyOutsideBehavior
DraggableBehavior
Inventory
LinkedObjects
PanelSpriteObject
ParticleSystem
PathfindingBehavior
PhysicsBehavior
PlatformBehavior
PrimitiveDrawing
Shopify
SystemInfo
TextEntryObject
TextObject
TiledSpriteObject
TopDownMovementBehavior)
# Automatically add all listed extensions
foreach(extension ${GD_EXTENSIONS})
add_subdirectory(${extension})
endforeach()

View File

@@ -7,79 +7,75 @@ macro(gd_add_extension_includes)
include_directories(${GDCORE_include_dir})
endmacro()
#Add common defines for a target that will be a GD extension
# Add common defines for a target that will be a GD extension
function(gd_add_extension_definitions target_name)
#Define used in GD to check the build type
IF(CMAKE_BUILD_TYPE MATCHES "Debug")
add_definitions( -DDEBUG )
ELSE()
add_definitions( -DRELEASE )
ENDIF()
# Define used in GD to check the build type
if("${CMAKE_BUILD_TYPE}" MATCHES "Debug")
add_definitions(-DDEBUG)
else()
add_definitions(-DRELEASE)
endif()
set(${target_name}_extra_definitions "${${target_name}_extra_definitions} GD_IDE_ONLY=1;" PARENT_SCOPE)
#Defne used in GD to identify the environment
IF (EMSCRIPTEN)
add_definitions( -DEMSCRIPTEN )
ELSEIF(WIN32)
add_definitions( -DWINDOWS )
ELSEIF(APPLE)
add_definitions( -DMACOS )
ELSE()
add_definitions( -DLINUX )
ENDIF()
# Define used in GD to identify the environment
if(EMSCRIPTEN)
add_definitions(-DEMSCRIPTEN)
elseif(WIN32)
add_definitions(-DWINDOWS)
elseif(APPLE)
add_definitions(-DMACOS)
else()
add_definitions(-DLINUX)
endif()
IF(WIN32) #Windows specific defines
add_definitions( "-DGD_CORE_API=__declspec(dllimport)" )
add_definitions( "-DGD_API=__declspec(dllimport)" )
add_definitions( "-DGD_EXTENSION_API=__declspec(dllexport)" )
add_definitions( -D__GNUWIN32__ )
ELSE()
add_definitions( -DGD_API= )
add_definitions( -DGD_CORE_API= )
add_definitions( -DGD_EXTENSION_API= )
ENDIF(WIN32)
if(WIN32) # Windows specific defines
add_definitions("-DGD_API=__declspec(dllimport)")
add_definitions("-DGD_CORE_API=__declspec(dllimport)")
add_definitions("-DGD_EXTENSION_API=__declspec(dllexport)")
add_definitions(-D__GNUWIN32__)
else()
add_definitions(-DGD_API=)
add_definitions(-DGD_CORE_API=)
add_definitions(-DGD_EXTENSION_API=)
endif()
endfunction()
#Add a GD extension target, that will produce the final library file.
# Add a GD extension target, that will produce the final library file.
function(gd_add_extension_target target_name source_files)
IF(target_name STREQUAL "")
MESSAGE(ERROR "You called gd_add_extension_target without specifying a target name")
ENDIF()
if(target_name STREQUAL "")
message(ERROR "You called gd_add_extension_target without specifying a target name")
endif()
SET(platform_directory ${ARGV2})
IF(NOT platform_directory)
SET(platform_directory "CppPlatform")
ENDIF()
set(platform_directory ${ARGV2})
if(NOT platform_directory)
set(platform_directory "CppPlatform")
endif()
IF(EMSCRIPTEN)
if(EMSCRIPTEN)
# Emscripten treats all libraries as static libraries
add_library(${target_name} STATIC ${source_files})
ELSE()
else()
add_library(${target_name} SHARED ${source_files})
ENDIF()
endif()
set_target_properties(${target_name} PROPERTIES PREFIX "")
set_target_properties(${target_name} PROPERTIES COMPILE_DEFINITIONS "${${target_name}_extra_definitions}")
set_target_properties(${target_name} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${GD_base_dir}/Binaries/Output/${CMAKE_BUILD_TYPE}_${CMAKE_SYSTEM_NAME}/${platform_directory}/Extensions")
set_target_properties(${target_name} PROPERTIES ARCHIVE_OUTPUT_DIRECTORY "${GD_base_dir}/Binaries/Output/${CMAKE_BUILD_TYPE}_${CMAKE_SYSTEM_NAME}/${platform_directory}/Extensions")
set_target_properties(${target_name} PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${GD_base_dir}/Binaries/Output/${CMAKE_BUILD_TYPE}_${CMAKE_SYSTEM_NAME}/${platform_directory}/Extensions")
IF(WIN32) #GD extensions have special suffix in their filenames.
if(WIN32) # GD extensions have special suffix in their filenames.
set_target_properties(${target_name} PROPERTIES SUFFIX ".xgdwe")
ELSEIF(EMSCRIPTEN)
elseif(EMSCRIPTEN)
set_target_properties(${target_name} PROPERTIES SUFFIX ".bc")
ELSE()
else()
set_target_properties(${target_name} PROPERTIES SUFFIX ".xgde")
ENDIF()
endif()
endfunction()
#Link default libraries with a target that is a GD extension
# Link default libraries with a target that is a GD extension
function(gd_extension_link_libraries target_name)
IF(EMSCRIPTEN)
#Nothing.
ELSE()
if(NOT EMSCRIPTEN)
target_link_libraries(${target_name} GDCore)
ENDIF()
endif()
endfunction()

View File

@@ -1,20 +1,23 @@
cmake_minimum_required(VERSION 2.6)
cmake_policy(SET CMP0015 NEW)
cmake_minimum_required(VERSION 3.5)
project(DestroyOutsideBehavior)
gd_add_extension_includes()
#Defines
###
# Defines
#
gd_add_extension_definitions(DestroyOutsideBehavior)
#The targets
###
# The targets
#
include_directories(.)
file(GLOB source_files *.cpp *.h)
file(
GLOB
source_files
*.cpp
*.h)
gd_add_clang_utils(DestroyOutsideBehavior "${source_files}")
gd_add_extension_target(DestroyOutsideBehavior "${source_files}")
#Linker files for the IDE extension
###
# Linker files for the IDE extension
#
gd_extension_link_libraries(DestroyOutsideBehavior GDCore)

View File

@@ -1,20 +1,23 @@
cmake_minimum_required(VERSION 2.6)
cmake_policy(SET CMP0015 NEW)
cmake_minimum_required(VERSION 3.5)
project(DraggableBehavior)
gd_add_extension_includes()
#Defines
###
# Defines
#
gd_add_extension_definitions(DraggableBehavior)
#The targets
###
# The targets
#
include_directories(.)
file(GLOB source_files *.cpp *.h)
file(
GLOB
source_files
*.cpp
*.h)
gd_add_clang_utils(DraggableBehavior "${source_files}")
gd_add_extension_target(DraggableBehavior "${source_files}")
#Linker files for the IDE extension
###
# Linker files for the IDE extension
#
gd_extension_link_libraries(DraggableBehavior)

View File

@@ -1,21 +1,23 @@
cmake_minimum_required(VERSION 2.6)
cmake_policy(SET CMP0015 NEW)
cmake_minimum_required(VERSION 3.5)
project(Inventory)
gd_add_extension_includes()
#Defines
###
# Defines
#
gd_add_extension_definitions(Inventory)
#The targets
###
# The targets
#
include_directories(.)
file(GLOB source_files *.cpp *.h)
file(
GLOB
source_files
*.cpp
*.h)
gd_add_clang_utils(Inventory "${source_files}")
gd_add_extension_target(Inventory "${source_files}")
#Linker files for the IDE extension
###
# Linker files for the IDE extension
#
gd_extension_link_libraries(Inventory)

View File

@@ -26,70 +26,57 @@ class InventoryJsExtension : public gd::PlatformExtension {
DeclareInventoryExtension(*this);
GetAllActions()["Inventory::Add"]
.codeExtraInformation
.SetIncludeFile("Extensions/Inventory/inventory.js")
.AddIncludeFile("Extensions/Inventory/inventorytools.js")
.SetFunctionName("gdjs.evtTools.inventory.add");
GetAllActions()["Inventory::Remove"]
.codeExtraInformation
.SetIncludeFile("Extensions/Inventory/inventory.js")
.AddIncludeFile("Extensions/Inventory/inventorytools.js")
.SetFunctionName("gdjs.evtTools.inventory.remove");
GetAllActions()["Inventory::SetMaximum"]
.codeExtraInformation
.SetIncludeFile("Extensions/Inventory/inventory.js")
.AddIncludeFile("Extensions/Inventory/inventorytools.js")
.SetFunctionName("gdjs.evtTools.inventory.setMaximum");
GetAllActions()["Inventory::SetUnlimited"]
.codeExtraInformation
.SetIncludeFile("Extensions/Inventory/inventory.js")
.AddIncludeFile("Extensions/Inventory/inventorytools.js")
.SetFunctionName("gdjs.evtTools.inventory.setUnlimited");
GetAllActions()["Inventory::Equip"]
.codeExtraInformation
.SetIncludeFile("Extensions/Inventory/inventory.js")
.AddIncludeFile("Extensions/Inventory/inventorytools.js")
.SetFunctionName("gdjs.evtTools.inventory.equip");
GetAllActions()["Inventory::SerializeToVariable"]
.codeExtraInformation
.SetIncludeFile("Extensions/Inventory/inventory.js")
.AddIncludeFile("Extensions/Inventory/inventorytools.js")
.SetFunctionName("gdjs.evtTools.inventory.serializeToVariable");
GetAllActions()["Inventory::UnserializeFromVariable"]
.codeExtraInformation
.SetIncludeFile("Extensions/Inventory/inventory.js")
.AddIncludeFile("Extensions/Inventory/inventorytools.js")
.SetFunctionName("gdjs.evtTools.inventory.unserializeFromVariable");
GetAllConditions()["Inventory::Count"]
.codeExtraInformation
.SetIncludeFile("Extensions/Inventory/inventory.js")
.AddIncludeFile("Extensions/Inventory/inventorytools.js")
.SetFunctionName("gdjs.evtTools.inventory.count");
GetAllConditions()["Inventory::Has"]
.codeExtraInformation
.SetIncludeFile("Extensions/Inventory/inventory.js")
.AddIncludeFile("Extensions/Inventory/inventorytools.js")
.SetFunctionName("gdjs.evtTools.inventory.has");
GetAllConditions()["Inventory::IsFull"]
.codeExtraInformation
.SetIncludeFile("Extensions/Inventory/inventory.js")
.AddIncludeFile("Extensions/Inventory/inventorytools.js")
.SetFunctionName("gdjs.evtTools.inventory.isFull");
GetAllConditions()["Inventory::IsEquipped"]
.codeExtraInformation
.SetIncludeFile("Extensions/Inventory/inventory.js")
.AddIncludeFile("Extensions/Inventory/inventorytools.js")
.SetFunctionName("gdjs.evtTools.inventory.isEquipped");
GetAllExpressions()["Inventory::Count"]
.codeExtraInformation
.SetIncludeFile("Extensions/Inventory/inventory.js")
.AddIncludeFile("Extensions/Inventory/inventorytools.js")
.SetFunctionName("gdjs.evtTools.inventory.count");
GetAllExpressions()["Inventory::Maximum"]
.codeExtraInformation
.SetIncludeFile("Extensions/Inventory/inventory.js")
.AddIncludeFile("Extensions/Inventory/inventorytools.js")
.SetFunctionName("gdjs.evtTools.inventory.maximum");

View File

@@ -59,11 +59,17 @@ module.exports = {
false
)
.addParameter('string', _('Name to register for the player'), '', false)
.setParameterLongDescription(
_(
'Let this empty to let the leaderboard auto-generate a player name (e.g: "Player23464"). You can configure this in the leaderboard administration.'
)
)
.setHelpPath('/all-features/leaderboards')
.getCodeExtraInformation()
.setIncludeFile('Extensions/Leaderboards/sha256.js')
.addIncludeFile('Extensions/Leaderboards/leaderboardstools.js')
.setFunctionName('gdjs.evtTools.leaderboards.savePlayerScore');
.setFunctionName('gdjs.evtTools.leaderboards.savePlayerScore')
.setAsyncFunctionName('gdjs.evtTools.leaderboards.savePlayerScore');
extension
.addAction(
@@ -89,7 +95,8 @@ module.exports = {
.getCodeExtraInformation()
.setIncludeFile('Extensions/Leaderboards/sha256.js')
.addIncludeFile('Extensions/Leaderboards/leaderboardstools.js')
.setFunctionName('gdjs.evtTools.leaderboards.saveConnectedPlayerScore');
.setFunctionName('gdjs.evtTools.leaderboards.saveConnectedPlayerScore')
.setAsyncFunctionName('gdjs.evtTools.leaderboards.saveConnectedPlayerScore');
extension
.addCondition(
@@ -154,20 +161,22 @@ module.exports = {
.setIncludeFile('Extensions/Leaderboards/leaderboardstools.js')
.setFunctionName('gdjs.evtTools.leaderboards.isSaving');
extension
.addCondition(
'HasPlayerJustClosedLeaderboardView',
_('Closed by player'),
_('Check if the player has just closed the leaderboard view.'),
_('Player has just closed the leaderboard view'),
_('Display leaderboard'),
'JsPlatform/Extensions/leaderboard.svg',
'JsPlatform/Extensions/leaderboard.svg'
)
.setHelpPath('/all-features/leaderboards')
.getCodeExtraInformation()
.setIncludeFile('Extensions/Leaderboards/leaderboardstools.js')
.setFunctionName('gdjs.evtTools.leaderboards.hasPlayerJustClosedLeaderboardView');
extension
.addCondition(
'HasPlayerJustClosedLeaderboardView',
_('Closed by player'),
_('Check if the player has just closed the leaderboard view.'),
_('Player has just closed the leaderboard view'),
_('Display leaderboard'),
'JsPlatform/Extensions/leaderboard.svg',
'JsPlatform/Extensions/leaderboard.svg'
)
.setHelpPath('/all-features/leaderboards')
.getCodeExtraInformation()
.setIncludeFile('Extensions/Leaderboards/leaderboardstools.js')
.setFunctionName(
'gdjs.evtTools.leaderboards.hasPlayerJustClosedLeaderboardView'
);
extension
.addStrExpression(

View File

@@ -24,37 +24,47 @@ namespace gdjs {
return shaObj.getHash('B64');
};
// Score saving
/**
* Hold the state of the save of a score for a leaderboard.
*/
class ScoreSavingState {
lastScoreSavingStartedAt: number | null;
lastScoreSavingSucceededAt: number | null;
currentlySavingScore: number | null;
currentlySavingPlayerName: string | null;
currentlySavingPlayerId: string | null;
lastSavedScore: number | null;
lastSavedPlayerName: string | null;
lastSavedPlayerId: string | null;
lastSaveError: string | null;
isScoreSaving: boolean;
hasScoreBeenSaved: boolean;
hasScoreSavingErrored: boolean;
lastScoreSavingStartedAt: number | null = null;
lastScoreSavingSucceededAt: number | null = null;
constructor() {
this.lastScoreSavingStartedAt = null;
this.lastScoreSavingSucceededAt = null;
this.currentlySavingScore = null;
this.currentlySavingPlayerName = null;
this.currentlySavingPlayerId = null;
this.lastSavedScore = null;
this.lastSavedPlayerName = null;
this.lastSavedPlayerId = null;
this.lastSaveError = null;
this.isScoreSaving = false;
this.hasScoreBeenSaved = false;
this.hasScoreSavingErrored = false;
/** The promise that will be resolved when the score saving is done (successfully or not). */
lastSavingPromise: Promise<void> | null = null;
// Score that is being saved:
private _currentlySavingScore: number | null = null;
private _currentlySavingPlayerName: string | null = null;
private _currentlySavingPlayerId: string | null = null;
// Last score saved with success:
private _lastSavedScore: number | null = null;
private _lastSavedPlayerName: string | null = null;
private _lastSavedPlayerId: string | null = null;
/** The id of the entry in the leaderboard, for the last score saved with success. */
lastSavedLeaderboardEntryId: string | null = null;
/** Last error that happened when saving the score (useful if `hasScoreSavingErrored` is true). */
lastSaveError: string | null = null;
/** `true` if the last save has finished and succeeded. */
hasScoreBeenSaved: boolean = false;
/** `true` if the last save has finished and failed (check `lastSaveError` then). */
hasScoreSavingErrored: boolean = false;
isSaving(): boolean {
return (
!!this.lastSavingPromise &&
!this.hasScoreBeenSaved &&
!this.hasScoreSavingErrored
);
}
isSameAsLastScore({
private _isSameAsLastScore({
playerName,
playerId,
score,
@@ -64,13 +74,13 @@ namespace gdjs {
score: number;
}): boolean {
return (
((!!playerName && this.lastSavedPlayerName === playerName) ||
(!!playerId && this.lastSavedPlayerId === playerId)) &&
this.lastSavedScore === score
((!!playerName && this._lastSavedPlayerName === playerName) ||
(!!playerId && this._lastSavedPlayerId === playerId)) &&
this._lastSavedScore === score
);
}
isAlreadySavingThisScore({
private _isAlreadySavingThisScore({
playerName,
playerId,
score,
@@ -79,15 +89,16 @@ namespace gdjs {
playerId?: string;
score: number;
}): boolean {
if (!this.isSaving()) return false;
return (
((!!playerName && this.currentlySavingPlayerName === playerName) ||
(!!playerId && this.currentlySavingPlayerId === playerId)) &&
this.isScoreSaving &&
this.currentlySavingScore === score
((!!playerName && this._currentlySavingPlayerName === playerName) ||
(!!playerId && this._currentlySavingPlayerId === playerId)) &&
this._currentlySavingScore === score
);
}
isTooSoonToSaveAnotherScore(): boolean {
private _isTooSoonToSaveAnotherScore(): boolean {
return (
!!this.lastScoreSavingStartedAt &&
Date.now() - this.lastScoreSavingStartedAt < 500
@@ -102,28 +113,91 @@ namespace gdjs {
playerName?: string;
playerId?: string;
score: number;
}): void {
}): {
closeSaving: (leaderboardEntryId: string | null) => void;
closeSavingWithError(errorCode: string);
} {
if (this._isAlreadySavingThisScore({ playerName, playerId, score })) {
logger.warn(
'There is already a request to save with this player name and this score. Ignoring this one.'
);
throw new Error('Ignoring this saving request.');
}
if (this._isSameAsLastScore({ playerName, playerId, score })) {
logger.warn(
'The player and score to be sent are the same as previous one. Ignoring this one.'
);
this._setError('SAME_AS_PREVIOUS');
throw new Error('Ignoring this saving request.');
}
if (this._isTooSoonToSaveAnotherScore()) {
logger.warn(
'Last entry was sent too little time ago. Ignoring this one.'
);
this._setError('TOO_FAST');
// Set the starting time to cancel all the following attempts that
// are started too early after this one.
this.lastScoreSavingStartedAt = Date.now();
throw new Error('Ignoring this saving request.');
}
let resolveSavingPromise: () => void;
const savingPromise = new Promise<void>((resolve) => {
resolveSavingPromise = resolve;
});
this.lastScoreSavingStartedAt = Date.now();
this.isScoreSaving = true;
this.lastSavingPromise = savingPromise;
this.hasScoreBeenSaved = false;
this.hasScoreSavingErrored = false;
this.currentlySavingScore = score;
if (playerName) this.currentlySavingPlayerName = playerName;
if (playerId) this.currentlySavingPlayerId = playerId;
this._currentlySavingScore = score;
if (playerName) this._currentlySavingPlayerName = playerName;
if (playerId) this._currentlySavingPlayerId = playerId;
return {
closeSaving: (leaderboardEntryId) => {
if (savingPromise !== this.lastSavingPromise) {
logger.info(
'Score saving result received, but another save was launched in the meantime - ignoring the result of this one.'
);
// Still finish the promise that can be waited upon:
resolveSavingPromise();
return;
}
this.lastScoreSavingSucceededAt = Date.now();
this._lastSavedScore = this._currentlySavingScore;
this._lastSavedPlayerName = this._currentlySavingPlayerName;
this._lastSavedPlayerId = this._currentlySavingPlayerId;
this.lastSavedLeaderboardEntryId = leaderboardEntryId;
this.hasScoreBeenSaved = true;
resolveSavingPromise();
},
closeSavingWithError: (errorCode) => {
if (savingPromise !== this.lastSavingPromise) {
logger.info(
'Score saving result received, but another save was launched in the meantime - ignoring the result of this one.'
);
// Still finish the promise that can be waited upon:
resolveSavingPromise();
return;
}
this._setError(errorCode);
resolveSavingPromise();
},
};
}
closeSaving(): void {
this.lastScoreSavingSucceededAt = Date.now();
this.lastSavedScore = this.currentlySavingScore;
this.lastSavedPlayerName = this.currentlySavingPlayerName;
this.lastSavedPlayerId = this.currentlySavingPlayerId;
this.isScoreSaving = false;
this.hasScoreBeenSaved = true;
}
setError(errorCode: string): void {
private _setError(errorCode: string): void {
this.lastSaveError = errorCode;
this.isScoreSaving = false;
this.hasScoreBeenSaved = false;
this.hasScoreSavingErrored = true;
}
@@ -172,6 +246,7 @@ namespace gdjs {
}
_loaderContainer.appendChild(_loader);
/** Get the saving state of the leaderboard who had the last update (successful or started). */
const getLastScoreSavingState = function ({
hasSucceeded,
}: {
@@ -201,19 +276,17 @@ namespace gdjs {
return lastScoreSavingState;
};
const saveScore = function ({
const saveScore = async function ({
leaderboardId,
playerName,
authenticatedPlayerData,
score,
scoreSavingState,
runtimeScene,
}: {
leaderboardId: string;
playerName?: string | null;
authenticatedPlayerData?: { playerId: string; playerToken: string };
score: number;
scoreSavingState: ScoreSavingState;
runtimeScene: gdjs.RuntimeScene;
}) {
const rootApi = runtimeScene
@@ -242,195 +315,143 @@ namespace gdjs {
] = `player-game-token ${authenticatedPlayerData.playerToken}`;
leaderboardEntryCreationUrl += `?playerId=${authenticatedPlayerData.playerId}`;
} else {
// In case playerName is empty or undefined, the formatting will generate a random name.
// In case playerName is empty, the backend will generate a random name.
payloadObject['playerName'] = formatPlayerName(playerName);
}
const payload = JSON.stringify(payloadObject);
headers['Digest'] = computeDigest(payload);
fetch(leaderboardEntryCreationUrl, {
body: payload,
method: 'POST',
headers: headers,
}).then(
(response) => {
if (!response.ok) {
const errorCode = response.status.toString();
logger.error(
'Server responded with an error:',
errorCode,
response.statusText
);
scoreSavingState.setError(errorCode);
return;
}
try {
const response = await fetch(leaderboardEntryCreationUrl, {
body: payload,
method: 'POST',
headers: headers,
});
scoreSavingState.closeSaving();
return response.text().then(
(text) => {},
(error) => {
logger.warn(
'An error occurred when reading response but score has been saved:',
error
);
}
if (!response.ok) {
const errorCode = response.status.toString();
logger.error(
'Server responded with an error:',
errorCode,
response.statusText
);
},
(error) => {
logger.error('Error while submitting a leaderboard score:', error);
const errorCode = 'REQUEST_NOT_SENT';
scoreSavingState.setError(errorCode);
throw errorCode;
}
);
let leaderboardEntryId: string | null = null;
try {
const leaderboardEntry = await response.json();
leaderboardEntryId = leaderboardEntry.id;
} catch (error) {
logger.warn(
'An error occurred when reading response but score has been saved:',
error
);
}
return leaderboardEntryId;
} catch (error) {
logger.error('Error while submitting a leaderboard score:', error);
const errorCode = 'REQUEST_NOT_SENT';
throw errorCode;
}
};
export const savePlayerScore = function (
export const savePlayerScore = (
runtimeScene: gdjs.RuntimeScene,
leaderboardId: string,
score: float,
playerName: string
) {
let scoreSavingState: ScoreSavingState;
if (_scoreSavingStateByLeaderboard[leaderboardId]) {
scoreSavingState = _scoreSavingStateByLeaderboard[leaderboardId];
let shouldStartSaving = true;
if (
shouldStartSaving &&
scoreSavingState.isAlreadySavingThisScore({ playerName, score })
) {
logger.warn(
'There is already a request to save with this player name and this score. Ignoring this one.'
);
shouldStartSaving = false;
}
) =>
new gdjs.PromiseTask(
(async () => {
const scoreSavingState = (_scoreSavingStateByLeaderboard[
leaderboardId
] =
_scoreSavingStateByLeaderboard[leaderboardId] ||
new ScoreSavingState());
if (
shouldStartSaving &&
scoreSavingState.isSameAsLastScore({ playerName, score })
) {
logger.warn(
'The player and score to be sent are the same as previous one. Ignoring this one.'
);
scoreSavingState.setError('SAME_AS_PREVIOUS');
shouldStartSaving = false;
}
try {
const {
closeSaving,
closeSavingWithError,
} = scoreSavingState.startSaving({ playerName, score });
if (
shouldStartSaving &&
scoreSavingState.isTooSoonToSaveAnotherScore()
) {
logger.warn(
'Last entry was sent too little time ago. Ignoring this one.'
);
scoreSavingState.setError('TOO_FAST');
shouldStartSaving = false;
// Set the starting time to cancel all the following attempts that
// are started too early after this one.
scoreSavingState.lastScoreSavingStartedAt = Date.now();
}
if (!shouldStartSaving) {
return;
}
} else {
scoreSavingState = new ScoreSavingState();
_scoreSavingStateByLeaderboard[leaderboardId] = scoreSavingState;
}
try {
const leaderboardEntryId = await saveScore({
leaderboardId,
playerName,
score,
runtimeScene,
});
closeSaving(leaderboardEntryId);
} catch (errorCode) {
closeSavingWithError(errorCode);
}
} catch {
// Do nothing: saving was rejected for a reason already logged.
}
})()
);
scoreSavingState.startSaving({ playerName, score });
saveScore({
leaderboardId,
playerName,
score,
scoreSavingState,
runtimeScene,
});
};
export const saveConnectedPlayerScore = function (
export const saveConnectedPlayerScore = (
runtimeScene: gdjs.RuntimeScene,
leaderboardId: string,
score: float
) {
let scoreSavingState: ScoreSavingState;
const playerId = gdjs.playerAuthentication.getUserId();
const playerToken = gdjs.playerAuthentication.getUserToken();
if (!playerId || !playerToken) {
logger.warn(
'Cannot save a score for a connected player if the player is not connected.'
);
return;
}
if (_scoreSavingStateByLeaderboard[leaderboardId]) {
scoreSavingState = _scoreSavingStateByLeaderboard[leaderboardId];
let shouldStartSaving = true;
if (
shouldStartSaving &&
scoreSavingState.isAlreadySavingThisScore({ playerId, score })
) {
logger.warn(
'There is already a request to save with this player ID and this score. Ignoring this one.'
);
shouldStartSaving = false;
}
) =>
new gdjs.PromiseTask(
(async () => {
const playerId = gdjs.playerAuthentication.getUserId();
const playerToken = gdjs.playerAuthentication.getUserToken();
if (!playerId || !playerToken) {
logger.warn(
'Cannot save a score for a connected player if the player is not connected.'
);
return;
}
if (
shouldStartSaving &&
scoreSavingState.isSameAsLastScore({ playerId, score })
) {
logger.warn(
'The player and score to be sent are the same as previous one. Ignoring this one.'
);
scoreSavingState.setError('SAME_AS_PREVIOUS');
shouldStartSaving = false;
}
const scoreSavingState = (_scoreSavingStateByLeaderboard[
leaderboardId
] =
_scoreSavingStateByLeaderboard[leaderboardId] ||
new ScoreSavingState());
if (
shouldStartSaving &&
scoreSavingState.isTooSoonToSaveAnotherScore()
) {
logger.warn(
'Last entry was sent too little time ago. Ignoring this one.'
);
scoreSavingState.setError('TOO_FAST');
shouldStartSaving = false;
// Set the starting time to cancel all the following attempts that
// are started too early after this one.
scoreSavingState.lastScoreSavingStartedAt = Date.now();
}
if (!shouldStartSaving) {
return;
}
} else {
scoreSavingState = new ScoreSavingState();
_scoreSavingStateByLeaderboard[leaderboardId] = scoreSavingState;
}
try {
const {
closeSaving,
closeSavingWithError,
} = scoreSavingState.startSaving({ playerId, score });
scoreSavingState.startSaving({ playerId, score });
saveScore({
leaderboardId,
authenticatedPlayerData: { playerId, playerToken },
score,
scoreSavingState,
runtimeScene,
});
};
try {
const leaderboardEntryId = await saveScore({
leaderboardId,
authenticatedPlayerData: { playerId, playerToken },
score,
runtimeScene,
});
closeSaving(leaderboardEntryId);
} catch (errorCode) {
closeSavingWithError(errorCode);
}
} catch {
// Do nothing: saving was rejected for a reason already logged.
}
})()
);
export const isSaving = function (leaderboardId?: string): boolean {
if (leaderboardId) {
return _scoreSavingStateByLeaderboard[leaderboardId]
? _scoreSavingStateByLeaderboard[leaderboardId].isScoreSaving
? _scoreSavingStateByLeaderboard[leaderboardId].isSaving()
: false;
}
const lastScoreSavingState = getLastScoreSavingState({
hasSucceeded: false,
});
return lastScoreSavingState
? lastScoreSavingState.isScoreSaving
: false;
return lastScoreSavingState ? lastScoreSavingState.isSaving() : false;
};
export const hasBeenSaved = function (leaderboardId?: string): boolean {
@@ -491,9 +512,7 @@ namespace gdjs {
typeof rawName !== 'string' ||
(typeof rawName === 'string' && rawName.length === 0)
) {
return `Player${Math.round(
(Math.random() * 9 + 1) * 10000 // Number between 10,000 and 99,999
)}`;
return '';
}
return rawName
.trim()
@@ -648,7 +667,7 @@ namespace gdjs {
return iframe;
};
export const displayLeaderboard = function (
export const displayLeaderboard = async function (
runtimeScene: gdjs.RuntimeScene,
leaderboardId: string,
displayLoader: boolean
@@ -682,81 +701,99 @@ namespace gdjs {
});
}
// If a save is being done for this leaderboard, wait for it to end so that the `lastSavedLeaderboardEntryId`
// can be saved and then used to show the player score.
const scoreSavingState = _scoreSavingStateByLeaderboard[leaderboardId];
if (scoreSavingState && scoreSavingState.lastSavingPromise) {
await scoreSavingState.lastSavingPromise;
}
const lastSavedLeaderboardEntryId = scoreSavingState
? scoreSavingState.lastSavedLeaderboardEntryId
: null;
const gameId = gdjs.projectData.properties.projectUuid;
const isDev = runtimeScene
.getGame()
.isUsingGDevelopDevelopmentEnvironment();
const targetUrl = `https://gd.games/games/${gameId}/leaderboard/${leaderboardId}?inGameEmbedded=true${
isDev ? '&dev=true' : ''
}`;
checkLeaderboardAvailability(targetUrl).then(
(isAvailable) => {
if (leaderboardId !== _requestedLeaderboardId) {
logger.warn(
`Received a response for leaderboard ${leaderboardId} though the last leaderboard requested is ${_requestedLeaderboardId}, ignoring this response.`
);
return;
}
if (!isAvailable) {
handleErrorDisplayingLeaderboard(
runtimeScene,
'Leaderboard data could not be fetched. Closing leaderboard view if there is one.'
);
return;
}
if (_leaderboardViewIframe) {
resetLeaderboardDisplayErrorTimeout(runtimeScene);
if (displayLoader) {
displayLoaderInLeaderboardView(true, runtimeScene, {
callOnErrorIfDomElementContainerMissing: false,
});
}
_leaderboardViewIframe.src = targetUrl;
} else {
const domElementContainer = runtimeScene
.getGame()
.getRenderer()
.getDomElementContainer();
if (!domElementContainer) {
handleErrorDisplayingLeaderboard(
runtimeScene,
"The div element covering the game couldn't be found, the leaderboard cannot be displayed."
);
return;
}
const searchParams = new URLSearchParams();
searchParams.set('inGameEmbedded', 'true');
if (isDev) searchParams.set('dev', 'true');
if (lastSavedLeaderboardEntryId)
searchParams.set(
'playerLeaderboardEntryId',
lastSavedLeaderboardEntryId
);
resetLeaderboardDisplayErrorTimeout(runtimeScene);
const targetUrl = `https://gd.games/games/${gameId}/leaderboard/${leaderboardId}?${searchParams}`;
_leaderboardViewIframe = computeLeaderboardDisplayingIframe(
targetUrl
);
if (typeof window !== 'undefined') {
_leaderboardViewClosingCallback = (event: MessageEvent) => {
receiveMessageFromLeaderboardView(
runtimeScene,
displayLoader,
event
);
};
(window as any).addEventListener(
'message',
_leaderboardViewClosingCallback,
true
);
}
domElementContainer.appendChild(_leaderboardViewIframe);
}
},
(err) => {
logger.error(err);
handleErrorDisplayingLeaderboard(
runtimeScene,
'An error occurred when fetching leaderboard data. Closing leaderboard view if there is one.'
try {
const isAvailable = await checkLeaderboardAvailability(targetUrl);
if (leaderboardId !== _requestedLeaderboardId) {
logger.warn(
`Received a response for leaderboard ${leaderboardId} though the last leaderboard requested is ${_requestedLeaderboardId}, ignoring this response.`
);
return;
}
);
if (!isAvailable) {
handleErrorDisplayingLeaderboard(
runtimeScene,
'Leaderboard data could not be fetched. Closing leaderboard view if there is one.'
);
return;
}
if (_leaderboardViewIframe) {
resetLeaderboardDisplayErrorTimeout(runtimeScene);
if (displayLoader) {
displayLoaderInLeaderboardView(true, runtimeScene, {
callOnErrorIfDomElementContainerMissing: false,
});
}
_leaderboardViewIframe.src = targetUrl;
} else {
const domElementContainer = runtimeScene
.getGame()
.getRenderer()
.getDomElementContainer();
if (!domElementContainer) {
handleErrorDisplayingLeaderboard(
runtimeScene,
"The div element covering the game couldn't be found, the leaderboard cannot be displayed."
);
return;
}
resetLeaderboardDisplayErrorTimeout(runtimeScene);
_leaderboardViewIframe = computeLeaderboardDisplayingIframe(
targetUrl
);
if (typeof window !== 'undefined') {
_leaderboardViewClosingCallback = (event: MessageEvent) => {
receiveMessageFromLeaderboardView(
runtimeScene,
displayLoader,
event
);
};
(window as any).addEventListener(
'message',
_leaderboardViewClosingCallback,
true
);
}
domElementContainer.appendChild(_leaderboardViewIframe);
}
} catch (err) {
logger.error(err);
handleErrorDisplayingLeaderboard(
runtimeScene,
'An error occurred when fetching leaderboard data. Closing leaderboard view if there is one.'
);
}
};
export const isLeaderboardViewErrored = function (): boolean {

View File

@@ -29,26 +29,14 @@ describe('Leaderboards', () => {
});
it('it generates a predefined player name with a random number if input is void/wrong type/empty', () => {
expect(gdjs.evtTools.leaderboards.formatPlayerName(null)).to.be('');
expect(gdjs.evtTools.leaderboards.formatPlayerName(undefined)).to.be('');
expect(gdjs.evtTools.leaderboards.formatPlayerName('')).to.be('');
// @ts-ignore
expect(gdjs.evtTools.leaderboards.formatPlayerName(null)).to.match(
/^Player\d{5}/
);
expect(gdjs.evtTools.leaderboards.formatPlayerName(5)).to.be('');
// @ts-ignore
expect(gdjs.evtTools.leaderboards.formatPlayerName(5)).to.match(
/^Player\d{5}/
);
// @ts-ignore
expect(gdjs.evtTools.leaderboards.formatPlayerName(undefined)).to.match(
/^Player\d{5}/
);
// @ts-ignore
expect(gdjs.evtTools.leaderboards.formatPlayerName(() => {})).to.match(
/^Player\d{5}/
);
// @ts-ignore
expect(gdjs.evtTools.leaderboards.formatPlayerName('')).to.match(
/^Player\d{5}/
);
expect(gdjs.evtTools.leaderboards.formatPlayerName(() => {})).to.be('');
});
it('it removes accents from latin letters', () => {

View File

@@ -1,20 +1,23 @@
cmake_minimum_required(VERSION 2.6)
cmake_policy(SET CMP0015 NEW)
cmake_minimum_required(VERSION 3.5)
project(LinkedObjects)
gd_add_extension_includes()
#Defines
###
# Defines
#
gd_add_extension_definitions(LinkedObjects)
#The targets
###
# The targets
#
include_directories(.)
file(GLOB source_files *.cpp *.h)
file(
GLOB
source_files
*.cpp
*.h)
gd_add_clang_utils(LinkedObjects "${source_files}")
gd_add_extension_target(LinkedObjects "${source_files}")
#Linker files for the IDE extension
###
gd_extension_link_libraries(LinkedObjects)
# Linker files for the IDE extension
#
gd_extension_link_libraries(LinkedObjects)

View File

@@ -26,23 +26,18 @@ class LinkedObjectsJsExtension : public gd::PlatformExtension {
DeclareLinkedObjectsExtension(*this);
GetAllActions()["LinkedObjects::LinkObjects"]
.codeExtraInformation
.SetIncludeFile("Extensions/LinkedObjects/linkedobjects.js")
.SetFunctionName("gdjs.evtTools.linkedObjects.linkObjects");
GetAllActions()["LinkedObjects::RemoveLinkBetween"]
.codeExtraInformation
.SetIncludeFile("Extensions/LinkedObjects/linkedobjects.js")
.SetFunctionName("gdjs.evtTools.linkedObjects.removeLinkBetween");
GetAllActions()["LinkedObjects::RemoveAllLinksOf"]
.codeExtraInformation
.SetIncludeFile("Extensions/LinkedObjects/linkedobjects.js")
.SetFunctionName("gdjs.evtTools.linkedObjects.removeAllLinksOf");
GetAllActions()["LinkedObjects::PickObjectsLinkedTo"]
.codeExtraInformation
.SetIncludeFile("Extensions/LinkedObjects/linkedobjects.js")
.SetFunctionName("gdjs.evtTools.linkedObjects.pickObjectsLinkedTo");
GetAllConditions()["LinkedObjects::PickObjectsLinkedTo"]
.codeExtraInformation
.SetIncludeFile("Extensions/LinkedObjects/linkedobjects.js")
.SetFunctionName("gdjs.evtTools.linkedObjects.pickObjectsLinkedTo");

View File

@@ -1,20 +1,23 @@
cmake_minimum_required(VERSION 2.6)
cmake_policy(SET CMP0015 NEW)
cmake_minimum_required(VERSION 3.5)
project(PanelSpriteObject)
gd_add_extension_includes()
#Defines
###
# Defines
#
gd_add_extension_definitions(PanelSpriteObject)
#The targets
###
# The targets
#
include_directories(.)
file(GLOB source_files *.cpp *.h)
file(
GLOB
source_files
*.cpp
*.h)
gd_add_clang_utils(PanelSpriteObject "${source_files}")
gd_add_extension_target(PanelSpriteObject "${source_files}")
#Linker files for the IDE extension
###
# Linker files for the IDE extension
#
gd_extension_link_libraries(PanelSpriteObject)

View File

@@ -38,7 +38,8 @@ void DeclarePanelSpriteObjectExtension(gd::PlatformExtension& extension) {
"from "
"the full image."),
"CppPlatform/Extensions/PanelSpriteIcon.png")
.SetCategoryFullName(_("General"));
.SetCategoryFullName(_("General"))
.MarkBaseObjectCapabilityAsSupported("resizable");
obj.AddCondition("Opacity",
_("Opacity"),
@@ -90,6 +91,7 @@ void DeclarePanelSpriteObjectExtension(gd::PlatformExtension& extension) {
.AddParameter("object", _("Object"), "PanelSprite")
.AddParameter("color", _("Tint"));
// Deprecated
obj.AddAction("Width",
_("Width"),
_("Modify the width of a Panel Sprite."),
@@ -101,9 +103,11 @@ void DeclarePanelSpriteObjectExtension(gd::PlatformExtension& extension) {
.AddParameter("object", _("Object"), "PanelSprite")
.UseStandardOperatorParameters("number",
gd::ParameterOptions::MakeNewOptions())
.SetHidden()
.SetFunctionName("SetWidth")
.SetGetter("GetWidth");
// Deprecated
obj.AddCondition("Width",
_("Width"),
_("Check the width of a Panel Sprite."),
@@ -115,8 +119,10 @@ void DeclarePanelSpriteObjectExtension(gd::PlatformExtension& extension) {
.AddParameter("object", _("Object"), "PanelSprite")
.UseStandardRelationalOperatorParameters(
"number", gd::ParameterOptions::MakeNewOptions())
.SetHidden()
.SetFunctionName("GetWidth");
// Deprecated
obj.AddAction("Height",
_("Height"),
_("Modify the height of a Panel Sprite."),
@@ -128,9 +134,11 @@ void DeclarePanelSpriteObjectExtension(gd::PlatformExtension& extension) {
.AddParameter("object", _("Object"), "PanelSprite")
.UseStandardOperatorParameters("number",
gd::ParameterOptions::MakeNewOptions())
.SetHidden()
.SetFunctionName("SetHeight")
.SetGetter("GetHeight");
// Deprecated
obj.AddCondition("Height",
_("Height"),
_("Check the height of a Panel Sprite."),
@@ -142,6 +150,7 @@ void DeclarePanelSpriteObjectExtension(gd::PlatformExtension& extension) {
.AddParameter("object", _("Object"), "PanelSprite")
.UseStandardRelationalOperatorParameters(
"number", gd::ParameterOptions::MakeNewOptions())
.SetHidden()
.SetFunctionName("SetHeight")
.SetGetter("GetHeight");

View File

@@ -1,21 +1,23 @@
cmake_minimum_required(VERSION 2.6)
cmake_policy(SET CMP0015 NEW)
cmake_minimum_required(VERSION 3.5)
project(ParticleSystem)
gd_add_extension_includes()
#Defines
###
# Defines
#
gd_add_extension_definitions(ParticleSystem)
#The targets
###
# The targets
#
include_directories(.)
file(GLOB source_files *.cpp *.h)
file(
GLOB
source_files
*.cpp
*.h)
gd_add_clang_utils(ParticleSystem "${source_files}")
gd_add_extension_target(ParticleSystem "${source_files}")
#Linker files for the IDE extension
###
# Linker files for the IDE extension
#
gd_extension_link_libraries(ParticleSystem)

View File

@@ -1,20 +1,23 @@
cmake_minimum_required(VERSION 2.6)
cmake_policy(SET CMP0015 NEW)
cmake_minimum_required(VERSION 3.5)
project(PathfindingBehavior)
gd_add_extension_includes()
#Defines
###
# Defines
#
gd_add_extension_definitions(PathfindingBehavior)
#The targets
###
# The targets
#
include_directories(.)
file(GLOB source_files *.cpp *.h)
file(
GLOB
source_files
*.cpp
*.h)
gd_add_clang_utils(PathfindingBehavior "${source_files}")
gd_add_extension_target(PathfindingBehavior "${source_files}")
#Linker files for the IDE extension
###
# Linker files for the IDE extension
#
gd_extension_link_libraries(PathfindingBehavior)

View File

@@ -1,21 +1,23 @@
cmake_minimum_required(VERSION 2.6)
cmake_policy(SET CMP0015 NEW)
cmake_minimum_required(VERSION 3.5)
project(PhysicsBehavior)
gd_add_extension_includes()
#Defines
###
# Defines
#
gd_add_extension_definitions(PhysicsBehavior)
#The targets
###
# The targets
#
include_directories(.)
file(GLOB source_files *.cpp *.h)
file(
GLOB
source_files
*.cpp
*.h)
gd_add_clang_utils(PhysicsBehavior "${source_files}")
gd_add_extension_target(PhysicsBehavior "${source_files}")
#Linker files for the IDE extension
###
# Linker files for the IDE extension
#
gd_extension_link_libraries(PhysicsBehavior)

View File

@@ -1,20 +1,23 @@
cmake_minimum_required(VERSION 2.6)
cmake_policy(SET CMP0015 NEW)
cmake_minimum_required(VERSION 3.5)
project(PlatformBehavior)
gd_add_extension_includes()
#Defines
###
# Defines
#
gd_add_extension_definitions(PlatformBehavior)
#The targets
###
# The targets
#
include_directories(.)
file(GLOB source_files *.cpp *.h)
file(
GLOB
source_files
*.cpp
*.h)
gd_add_clang_utils(PlatformBehavior "${source_files}")
gd_add_extension_target(PlatformBehavior "${source_files}")
#Linker files for the IDE extension
###
gd_extension_link_libraries(PlatformBehavior)
# Linker files for the IDE extension
#
gd_extension_link_libraries(PlatformBehavior)

View File

@@ -1,20 +1,23 @@
cmake_minimum_required(VERSION 2.6)
cmake_policy(SET CMP0015 NEW)
cmake_minimum_required(VERSION 3.5)
project(PrimitiveDrawing)
gd_add_extension_includes()
#Defines
###
# Defines
#
gd_add_extension_definitions(PrimitiveDrawing)
#The targets
###
# The targets
#
include_directories(.)
file(GLOB source_files *.cpp *.h)
file(
GLOB
source_files
*.cpp
*.h)
gd_add_clang_utils(PrimitiveDrawing "${source_files}")
gd_add_extension_target(PrimitiveDrawing "${source_files}")
#Linker files for the IDE extension
###
# Linker files for the IDE extension
#
gd_extension_link_libraries(PrimitiveDrawing)

View File

@@ -31,6 +31,9 @@ void DeclarePrimitiveDrawingExtension(gd::PlatformExtension& extension) {
_("Allows you to draw simple shapes on the screen using the "
"events."),
"CppPlatform/Extensions/primitivedrawingicon.png")
.MarkBaseObjectCapabilityAsSupported("resizable")
.MarkBaseObjectCapabilityAsSupported("scalable")
.MarkBaseObjectCapabilityAsSupported("flippable")
.SetCategoryFullName(_("Advanced"));
#if defined(GD_IDE_ONLY)
@@ -612,6 +615,7 @@ void DeclarePrimitiveDrawingExtension(gd::PlatformExtension& extension) {
.AddParameter("object", _("Shape Painter object"), "Drawer")
.SetFunctionName("AreCoordinatesRelative");
// Deprecated
obj.AddAction("Scale",
_("Scale"),
_("Modify the scale of the specified object."),
@@ -624,8 +628,10 @@ void DeclarePrimitiveDrawingExtension(gd::PlatformExtension& extension) {
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Scale (1 by default)")))
.SetHidden()
.MarkAsAdvanced();
// Deprecated
obj.AddExpressionAndConditionAndAction("number",
"ScaleX",
_("Scale on X axis"),
@@ -638,8 +644,10 @@ void DeclarePrimitiveDrawingExtension(gd::PlatformExtension& extension) {
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Scale (1 by default)")))
.SetHidden()
.MarkAsAdvanced();
// Deprecated
obj.AddExpressionAndConditionAndAction("number",
"ScaleY",
_("Scale on Y axis"),
@@ -652,6 +660,7 @@ void DeclarePrimitiveDrawingExtension(gd::PlatformExtension& extension) {
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Scale (1 by default)")))
.SetHidden()
.MarkAsAdvanced();
obj.AddAction("FlipX",
@@ -663,6 +672,7 @@ void DeclarePrimitiveDrawingExtension(gd::PlatformExtension& extension) {
"res/actions/flipX.png")
.AddParameter("object", _("Object"), "Drawer")
.AddParameter("yesorno", _("Activate flipping"))
.SetHidden()
.MarkAsSimple();
obj.AddAction("FlipY",
@@ -674,6 +684,7 @@ void DeclarePrimitiveDrawingExtension(gd::PlatformExtension& extension) {
"res/actions/flipY.png")
.AddParameter("object", _("Object"), "Drawer")
.AddParameter("yesorno", _("Activate flipping"))
.SetHidden()
.MarkAsSimple();
obj.AddCondition("FlippedX",
@@ -683,7 +694,8 @@ void DeclarePrimitiveDrawingExtension(gd::PlatformExtension& extension) {
_("Effects"),
"res/actions/flipX24.png",
"res/actions/flipX.png")
.AddParameter("object", _("Object"), "Drawer");
.AddParameter("object", _("Object"), "Drawer")
.SetHidden();
obj.AddCondition("FlippedY",
_("Vertically flipped"),
@@ -692,8 +704,10 @@ void DeclarePrimitiveDrawingExtension(gd::PlatformExtension& extension) {
_("Effects"),
"res/actions/flipY24.png",
"res/actions/flipY.png")
.AddParameter("object", _("Object"), "Drawer");
.AddParameter("object", _("Object"), "Drawer")
.SetHidden();
// Deprecated
obj.AddAction("Width",
_("Width"),
_("Change the width of an object."),
@@ -704,8 +718,10 @@ void DeclarePrimitiveDrawingExtension(gd::PlatformExtension& extension) {
.AddParameter("object", _("Object"), "Drawer")
.UseStandardOperatorParameters("number",
gd::ParameterOptions::MakeNewOptions())
.SetHidden()
.MarkAsAdvanced();
// Deprecated
obj.AddAction("Height",
_("Height"),
_("Change the height of an object."),
@@ -716,6 +732,7 @@ void DeclarePrimitiveDrawingExtension(gd::PlatformExtension& extension) {
.AddParameter("object", _("Object"), "Drawer")
.UseStandardOperatorParameters("number",
gd::ParameterOptions::MakeNewOptions())
.SetHidden()
.MarkAsAdvanced();
obj.AddAction(

View File

@@ -1,21 +1,26 @@
cmake_minimum_required(VERSION 2.6)
cmake_policy(SET CMP0015 NEW)
cmake_minimum_required(VERSION 3.5)
project(Shopify)
gd_add_extension_includes()
#Defines
###
# Defines
#
gd_add_extension_definitions(Shopify)
#The targets
###
# The targets
#
include_directories(.)
file(GLOB source_files *.cpp *.h)
gd_add_extension_target(Shopify "${source_files}" "JsPlatform")
file(
GLOB
source_files
*.cpp
*.h)
gd_add_extension_target(
Shopify
"${source_files}"
"JsPlatform")
gd_add_clang_utils(Shopify "${source_files}")
#Linker files for the IDE extension
###
# Linker files for the IDE extension
#
gd_extension_link_libraries(Shopify)

View File

@@ -81,12 +81,10 @@ class ShopifyJsExtension : public gd::PlatformExtension {
DeclareShopifyExtension(*this);
GetAllActions()["Shopify::BuildClient"]
.codeExtraInformation
.SetIncludeFile("Extensions/Shopify/shopify-buy.umd.polyfilled.min.js")
.AddIncludeFile("Extensions/Shopify/shopifytools.js")
.SetFunctionName("gdjs.evtTools.shopify.buildClient");
GetAllActions()["Shopify::GetCheckoutUrlForProduct"]
.codeExtraInformation
.SetIncludeFile("Extensions/Shopify/shopify-buy.umd.polyfilled.min.js")
.AddIncludeFile("Extensions/Shopify/shopifytools.js")
.SetFunctionName("gdjs.evtTools.shopify.getCheckoutUrlForProduct");

File diff suppressed because it is too large Load Diff

View File

@@ -1,63 +0,0 @@
namespace gdjs {
export namespace steamworks {
gdjs.registerFirstRuntimeSceneLoadedCallback(() => {
if (gdjs.steamworks.steamAPI) gdjs.steamworks.steamAPI.input.init();
});
export function getControllerCount(): integer {
return gdjs.steamworks.steamAPI
? gdjs.steamworks.steamAPI.input.getControllers().length
: 0;
}
export function activateActionSet(
controllerIndex: number,
actionSetName: string
): void {
if (!gdjs.steamworks.steamAPI) return;
gdjs.steamworks.steamAPI.input
.getControllers()
[controllerIndex]?.activateActionSet(
gdjs.steamworks.steamAPI.input.getActionSet(actionSetName)
);
}
export function isDigitalActionPressed(
controllerIndex: number,
actionName: string
): boolean {
if (!gdjs.steamworks.steamAPI) return false;
return !!gdjs.steamworks.steamAPI.input
.getControllers()
[controllerIndex]?.isDigitalActionPressed(
gdjs.steamworks.steamAPI.input.getDigitalAction(actionName)
);
}
export function getAnalogActionVectorX(
controllerIndex: number,
actionName: string
): float {
return gdjs.steamworks.steamAPI
? gdjs.steamworks.steamAPI.input
.getControllers()
[controllerIndex]?.getAnalogActionVector(
gdjs.steamworks.steamAPI.input.getAnalogAction(actionName)
).x ?? 0
: 0;
}
export function getAnalogActionVectorY(
controllerIndex: number,
actionName: string
): float {
return gdjs.steamworks.steamAPI
? gdjs.steamworks.steamAPI.input
.getControllers()
[controllerIndex]?.getAnalogActionVector(
gdjs.steamworks.steamAPI.input.getAnalogAction(actionName)
).y ?? 0
: 0;
}
}
}

View File

@@ -1,566 +0,0 @@
namespace gdjs {
export namespace steamworks {
const logger = new gdjs.Logger('Steamworks');
export let steamAPI: import('steamworks.js').Client | null = null;
gdjs.registerFirstRuntimeSceneLoadedCallback((runtimeScene) => {
const remote = runtimeScene.getGame().getRenderer().getElectronRemote();
if (!remote) return; // Steamworks is only supported on electron
const steamworks_js = remote.require(
'steamworks.js'
) as typeof import('steamworks.js');
// Sets the proper electron flags for the steam overlay to function properly
steamworks_js.electronEnableSteamOverlay();
const unparsedAppID = runtimeScene
.getGame()
.getExtensionProperty('Steamworks', 'AppID');
if (!unparsedAppID) {
logger.error(
'A steam AppID needs to be configured in the game properties for steamworks features to be used!'
);
return;
}
const appID = parseInt(unparsedAppID, 10);
// Restart the game through steam if it needs to be launched with steam but has not been
if (
runtimeScene
.getGame()
.getExtensionProperty('Steamworks', 'RequireSteam') &&
!runtimeScene.getGame().isPreview() &&
steamworks_js.restartAppIfNecessary(appID)
) {
remote.process.exit(1);
return;
}
steamAPI = steamworks_js.init(appID);
});
// ---
export function claimAchievement(achievement: string): void {
if (steamAPI) steamAPI.achievement.activate(achievement);
else
logger.warn(
`Could not claim achievement ${achievement}, steamworks was not properly loaded!`
);
}
export function unclaimAchievement(achievement: string): void {
if (steamAPI) steamAPI.achievement.clear(achievement);
else
logger.warn(
`Could not unclaim achievement ${achievement}, steamworks was not properly loaded!`
);
}
export function hasAchievement(achievement: string): boolean {
return !!steamAPI && steamAPI.achievement.isActivated(achievement);
}
// ---
export function getSteamId(): string {
return steamAPI
? steamAPI.localplayer.getSteamId().steamId64.toString(10)
: '';
}
export function getName(): string {
return steamAPI ? steamAPI.localplayer.getName() : 'Unknown';
}
export function getCountry(): string {
return steamAPI ? steamAPI.localplayer.getIpCountry() : 'Unknown';
}
export function getLevel(): number {
return steamAPI ? steamAPI.localplayer.getLevel() : 0;
}
export function setRichPresence(key: string, value: string): void {
if (steamAPI) steamAPI.localplayer.setRichPresence(key, value);
else
logger.warn(
`Could not set the rich presence, steamworks was not properly loaded!`
);
}
// ---
export function isSteamworksProperlyLoaded(): boolean {
return !!steamAPI;
}
export function getAppID(): number {
return steamAPI ? steamAPI.utils.getAppId() : 0;
}
export function getServerRealTime(): number {
return steamAPI ? steamAPI.utils.getServerRealTime() : Date.now();
}
export function isOnSteamDeck(): boolean {
return steamAPI ? steamAPI.utils.isSteamRunningOnSteamDeck() : false;
}
// ---
enum LobbyType {
Private = 0,
FriendsOnly = 1,
Public = 2,
Invisible = 3,
}
const knownLobbies = new Map<
string,
import('steamworks.js/client').matchmaking.Lobby
>();
let currentLobby:
| import('steamworks.js/client').matchmaking.Lobby
| null = null;
export function getKnownLobby(lobbyId: string) {
if (!steamAPI) {
logger.warn(
`Could not access lobby '${lobbyId}', steamworks was not properly loaded!`
);
return null;
}
const lobby = knownLobbies.get(lobbyId);
if (!lobby) {
logger.error(
`Could not access lobby '${lobbyId}'! You might need to join it before trying to access it.`
);
return null;
}
return lobby;
}
export function createLobby(
lobbyType: 'Private' | 'FriendsOnly' | 'Public' | 'Invisible',
maxPlayers: number,
result: gdjs.Variable
): gdjs.AsyncTask {
if (steamAPI) {
return new gdjs.PromiseTask(
steamAPI.matchmaking
.createLobby(
LobbyType[lobbyType] as any /* Const enums are 😩 */,
maxPlayers
)
.then((lobby) => {
const id = lobby.id.toString(10);
knownLobbies.set(id, lobby);
currentLobby = lobby;
result.setString(id);
})
.catch(() => {
result.setString('failure');
})
);
} else {
logger.warn(
`Could not create a lobby, steamworks was not properly loaded!`
);
return new gdjs.ResolveTask();
}
}
export function getLobbiesList(results: gdjs.Variable): gdjs.AsyncTask {
if (steamAPI) {
return new gdjs.PromiseTask(
steamAPI.matchmaking
.getLobbies()
.then((lobbies) => {
const allLobbiesIds = lobbies.map((lobby) => {
const id = lobby.id.toString(10);
knownLobbies.set(id, lobby);
return id;
});
results.fromJSObject(allLobbiesIds);
})
.catch(() => {
results.setString('failure');
})
);
} else {
logger.warn(
`Could not obtain the lobbies list, steamworks was not properly loaded!`
);
return new gdjs.ResolveTask();
}
}
export function joinLobby(
lobbyId: string,
result: gdjs.Variable
): gdjs.AsyncTask {
if (steamAPI) {
return new gdjs.PromiseTask(
steamAPI.matchmaking
.joinLobby(BigInt(lobbyId))
.then((lobby) => {
knownLobbies.set(lobbyId, lobby);
currentLobby = lobby;
result.setString(lobbyId);
})
.catch(() => {
result.setString('failure');
})
);
} else {
logger.warn(
`Could not join a lobby, steamworks was not properly loaded!`
);
return new gdjs.ResolveTask();
}
}
export function getCurrentLobbyId(): string {
return currentLobby ? currentLobby.id.toString(10) : 'none';
}
export function leaveCurrentLobby(): void {
if (currentLobby) currentLobby.leave();
}
export function openDialogForInvitingUsersToTheCurrentLobby(): void {
if (currentLobby) currentLobby.openInviteDialog();
}
export function getCurrentLobbyAttribute(attribute: string): string {
if (!currentLobby) return '';
const data = currentLobby.getData(attribute);
return data === null ? '' : data;
}
export function getLobbyAttribute(
lobbyId: string,
attribute: string
): string {
const lobby = getKnownLobby(lobbyId);
if (!lobby) return '';
const data = lobby.getData(attribute);
return data === null ? '' : data;
}
export function setCurrentLobbyAttribute(
attribute: string,
value: string,
success: gdjs.Variable
): void {
if (currentLobby)
success.setBoolean(currentLobby.setData(attribute, value));
}
export function setCurrentLobbyJoinability(
shouldBeJoinable: boolean,
success: gdjs.Variable
): void {
if (currentLobby)
success.setBoolean(currentLobby.setJoinable(shouldBeJoinable));
}
export function getCurrentLobbyMemberCount(): number {
return currentLobby ? Number(currentLobby.getMemberCount()) : 0;
}
export function getLobbyMemberCount(lobbyId: string): number {
const lobby = getKnownLobby(lobbyId);
return lobby ? Number(lobby.getMemberCount()) : 0;
}
export function getCurrentLobbyMemberLimit(): number {
return currentLobby ? Number(currentLobby.getMemberLimit()) : 0;
}
export function getLobbyMemberLimit(lobbyId: string): number {
const lobby = getKnownLobby(lobbyId);
if (!lobby) return 0;
return lobby ? Number(lobby.getMemberLimit()) : 0;
}
export function getCurrentLobbyOwner(): string {
return currentLobby ? currentLobby.getOwner().steamId64.toString(10) : '';
}
export function getLobbyOwner(lobbyId: string): string {
const lobby = getKnownLobby(lobbyId);
return lobby ? lobby.getOwner().steamId64.toString(10) : '';
}
export function getCurrentLobbyMembersList(storeIn: gdjs.Variable): void {
if (currentLobby) {
storeIn.fromJSObject(
currentLobby
.getMembers()
.map((steamID) => steamID.steamId64.toString(10))
);
}
}
export function getLobbyMembersList(
lobbyId: string,
storeIn: gdjs.Variable
): void {
const lobby = getKnownLobby(lobbyId);
if (lobby) {
storeIn.fromJSObject(
lobby.getMembers().map((steamID) => steamID.steamId64.toString(10))
);
}
}
// ---
export function isAppOwned(appId: string): boolean {
return !!steamAPI && steamAPI.apps.isSubscribedApp(Number(appId));
}
export function isAppInstalled(appId: string): boolean {
return !!steamAPI && steamAPI.apps.isAppInstalled(Number(appId));
}
export function isDLCInstalled(dlcId: string): boolean {
return !!steamAPI && steamAPI.apps.isDlcInstalled(Number(dlcId));
}
export function getAppInstallDirectory(appId: string): string {
return steamAPI ? steamAPI.apps.appInstallDir(Number(appId)) : '';
}
export function isVacBanned(): boolean {
return !!steamAPI && steamAPI.apps.isVacBanned();
}
export function isLowViolence(): boolean {
return !!steamAPI && steamAPI.apps.isLowViolence();
}
export function userBoughtTheGame(): boolean {
return !!steamAPI && steamAPI.apps.isSubscribed();
}
export function currentGameLanguage(): string {
return steamAPI ? steamAPI.apps.currentGameLanguage() : '';
}
export function currentBetaName(): string {
return steamAPI ? steamAPI.apps.currentBetaName() || '' : '';
}
export function getBuildId(): number {
return steamAPI ? steamAPI.apps.appBuildId() : 0;
}
// ---
export function isCloudEnabled(): boolean {
return (
!!steamAPI &&
steamAPI.cloud.isEnabledForAccount() &&
steamAPI.cloud.isEnabledForApp()
);
}
export function readFile(fileName: string): string {
return steamAPI ? steamAPI.cloud.readFile(fileName) : '';
}
export function writeFile(
fileName: string,
content: string,
results: gdjs.Variable
): void {
if (steamAPI)
results.setBoolean(steamAPI.cloud.writeFile(fileName, content));
}
export function fileExists(fileName: string): boolean {
return steamAPI ? steamAPI.cloud.fileExists(fileName) : false;
}
export function deleteFile(fileName: string, results: gdjs.Variable): void {
if (steamAPI) results.setBoolean(steamAPI.cloud.deleteFile(fileName));
}
// ---
export function createWorkshopItem(result: gdjs.Variable): gdjs.AsyncTask {
if (steamAPI)
return new gdjs.PromiseTask(
steamAPI.workshop
.createItem()
.then(({ itemId }) => {
result.setString(itemId.toString());
})
.catch(() => {
result.setString('failure');
})
);
else {
result.setString('failure');
return new gdjs.ResolveTask();
}
}
enum UgcItemVisibility {
Public = 0,
FriendsOnly = 1,
Private = 2,
Unlisted = 3,
}
export function updateWorkshopItem(
itemId: string,
title: string,
description: string,
changeNote: string,
previewPath: string,
contentPath: string,
tags: string,
visibility: keyof import('steamworks.js/client').workshop.UgcItemVisibility,
result: gdjs.Variable
): gdjs.AsyncTask {
if (steamAPI) {
const changes: import('steamworks.js/client').workshop.UgcUpdate = {};
if (title) changes.title = title;
if (description) changes.description = description;
if (changeNote) changes.changeNote = changeNote;
if (previewPath) changes.previewPath = previewPath;
if (contentPath) changes.contentPath = contentPath;
if (tags) changes.tags = tags.split(',');
if (visibility)
//@ts-ignore const enum 😩
changes.visibility = UgcItemVisibility[visibility];
return new gdjs.PromiseTask(
steamAPI.workshop
.updateItem(BigInt(itemId), changes)
.then(() => {
result.setBoolean(true);
})
.catch(() => {
result.setBoolean(false);
})
);
} else {
result.setBoolean(false);
return new gdjs.ResolveTask();
}
}
export function subscribeToWorkshopItem(
itemId: string,
result: gdjs.Variable
): gdjs.AsyncTask {
if (steamAPI)
return new gdjs.PromiseTask(
steamAPI.workshop
.subscribe(BigInt(itemId))
.then(() => {
result.setBoolean(true);
})
.catch(() => {
result.setBoolean(false);
})
);
else {
result.setBoolean(false);
return new gdjs.ResolveTask();
}
}
export function unsubscribeToWorkshopItem(
itemId: string,
result: gdjs.Variable
): gdjs.AsyncTask {
if (steamAPI)
return new gdjs.PromiseTask(
steamAPI.workshop
.unsubscribe(BigInt(itemId))
.then(() => {
result.setBoolean(true);
})
.catch(() => {
result.setBoolean(false);
})
);
else {
result.setBoolean(false);
return new gdjs.ResolveTask();
}
}
export function startWorkshopDownload(
itemId: string,
highPriority: boolean
): void {
if (steamAPI) steamAPI.workshop.download(BigInt(itemId), highPriority);
}
enum WorkshopItemStates {
None = 0,
Subscribed = 1,
LegacyItem = 2,
Installed = 4,
NeedsUpdate = 8,
Downloading = 16,
DownloadPending = 32,
}
export function workshopItemState(
itemId: string,
state: keyof WorkshopItemStates
): boolean {
return (
!!steamAPI &&
(steamAPI.workshop.state(BigInt(itemId)) &
WorkshopItemStates[state]) !==
0
);
}
export function getWorkshopItemLocation(itemId: string): string {
return steamAPI
? steamAPI.workshop.installInfo(BigInt(itemId))?.folder || ''
: '';
}
export function getWorkshopItemSizeOnDisk(itemId: string): number {
return steamAPI
? Number(steamAPI.workshop.installInfo(BigInt(itemId))?.sizeOnDisk) || 0
: 0;
}
export function getWorkshopItemInstallTimestamp(itemId: string): number {
return steamAPI
? steamAPI.workshop.installInfo(BigInt(itemId))?.timestamp || 0
: 0;
}
export function getWorkshopItemDownloadProgress(itemId: string): number {
return steamAPI
? Number(steamAPI.workshop.downloadInfo(BigInt(itemId))?.current) || 0
: 0;
}
export function getWorkshopItemDownloadTotal(itemId: string): number {
return steamAPI
? Number(steamAPI.workshop.downloadInfo(BigInt(itemId))?.total) || 0
: 0;
}
}
}

View File

@@ -1,362 +0,0 @@
declare module 'steamworks.js/client' {
export function init(appId: number): void;
export function restartAppIfNecessary(appId: number): boolean;
export function runCallbacks(): void;
export interface PlayerSteamId {
steamId64: bigint;
steamId32: string;
accountId: number;
}
export namespace achievement {
export function activate(achievement: string): boolean;
export function isActivated(achievement: string): boolean;
export function clear(achievement: string): boolean;
}
export namespace apps {
export function isSubscribedApp(appId: number): boolean;
export function isAppInstalled(appId: number): boolean;
export function isDlcInstalled(appId: number): boolean;
export function isSubscribedFromFreeWeekend(): boolean;
export function isVacBanned(): boolean;
export function isCybercafe(): boolean;
export function isLowViolence(): boolean;
export function isSubscribed(): boolean;
export function appBuildId(): number;
export function appInstallDir(appId: number): string;
export function appOwner(): PlayerSteamId;
export function availableGameLanguages(): Array<string>;
export function currentGameLanguage(): string;
export function currentBetaName(): string | null;
}
export namespace auth {
/** @param timeoutSeconds - The number of seconds to wait for the ticket to be validated. Default value is 10 seconds. */
export function getSessionTicket(
timeoutSeconds?: number | undefined | null
): Promise<Ticket>;
export class Ticket {
cancel(): void;
getBytes(): Buffer;
}
}
export const enum ChatMemberStateChange {
/** This user has joined or is joining the lobby. */
Entered,
/** This user has left or is leaving the lobby. */
Left,
/** User disconnected without leaving the lobby first. */
Disconnected,
/** The user has been kicked. */
Kicked,
/** The user has been kicked and banned. */
Banned,
}
export interface CallbackReturns {
[callback.SteamCallback.PersonaStateChange]: {
steam_id: bigint;
flags: { bits: number };
};
[callback.SteamCallback.SteamServersConnected]: {};
[callback.SteamCallback.SteamServersDisconnected]: {
reason: number;
};
[callback.SteamCallback.SteamServerConnectFailure]: {
reason: number;
still_retrying: boolean;
};
[callback.SteamCallback.LobbyDataUpdate]: {
lobby: bigint;
member: bigint;
success: boolean;
};
[callback.SteamCallback.LobbyChatUpdate]: {
lobby: bigint;
user_changed: bigint;
making_change: bigint;
member_state_change: ChatMemberStateChange;
};
[callback.SteamCallback.P2PSessionRequest]: {
remote: bigint;
};
[callback.SteamCallback.P2PSessionConnectFail]: {
remote: bigint;
error: number;
};
[callback.SteamCallback.GameLobbyJoinRequested]: {
lobby_steam_id: bigint;
friend_steam_id: bigint;
};
[callback.SteamCallback.MicroTxnAuthorizationResponse]: {
app_id: number;
order_id: number | bigint;
authorized: boolean;
};
}
export namespace callback {
export const enum SteamCallback {
PersonaStateChange = 0,
SteamServersConnected = 1,
SteamServersDisconnected = 2,
SteamServerConnectFailure = 3,
LobbyDataUpdate = 4,
LobbyChatUpdate = 5,
P2PSessionRequest = 6,
P2PSessionConnectFail = 7,
GameLobbyJoinRequested = 8,
MicroTxnAuthorizationResponse = 9,
}
export function register<C extends keyof CallbackReturns>(
steamCallback: C,
handler: (value: CallbackReturns[C]) => void
): Handle;
export class Handle {
disconnect(): void;
}
}
export namespace cloud {
export function isEnabledForAccount(): boolean;
export function isEnabledForApp(): boolean;
export function readFile(name: string): string;
export function writeFile(name: string, content: string): boolean;
export function deleteFile(name: string): boolean;
export function fileExists(name: string): boolean;
}
export namespace input {
export interface AnalogActionVector {
x: number;
y: number;
}
export function init(): void;
export function getControllers(): Array<Controller>;
export function getActionSet(actionSetName: string): bigint;
export function getDigitalAction(actionName: string): bigint;
export function getAnalogAction(actionName: string): bigint;
export function shutdown(): void;
export class Controller {
activateActionSet(actionSetHandle: bigint): void;
isDigitalActionPressed(actionHandle: bigint): boolean;
getAnalogActionVector(actionHandle: bigint): AnalogActionVector;
}
}
export namespace localplayer {
export function getSteamId(): PlayerSteamId;
export function getName(): string;
export function getLevel(): number;
/** @returns the 2 digit ISO 3166-1-alpha-2 format country code which client is running in, e.g. "US" or "UK". */
export function getIpCountry(): string;
export function setRichPresence(
key: string,
value?: string | undefined | null
): void;
}
export namespace matchmaking {
export const enum LobbyType {
Private = 0,
FriendsOnly = 1,
Public = 2,
Invisible = 3,
}
export function createLobby(
lobbyType: LobbyType,
maxMembers: number
): Promise<Lobby>;
export function joinLobby(lobbyId: bigint): Promise<Lobby>;
export function getLobbies(): Promise<Array<Lobby>>;
export class Lobby {
id: bigint;
join(): Promise<Lobby>;
leave(): void;
openInviteDialog(): void;
getMemberCount(): bigint;
getMemberLimit(): bigint | null;
getMembers(): Array<PlayerSteamId>;
getOwner(): PlayerSteamId;
setJoinable(joinable: boolean): boolean;
getData(key: string): string | null;
setData(key: string, value: string): boolean;
deleteData(key: string): boolean;
/** Get an object containing all the lobby data */
getFullData(): Record<string, string>;
/**
* Merge current lobby data with provided data in a single batch
* @returns true if all data was set successfully
*/
mergeFullData(data: Record<string, string>): boolean;
}
}
export namespace networking {
export interface P2PPacket {
data: Buffer;
size: number;
steamId: PlayerSteamId;
}
/** The method used to send a packet */
export const enum SendType {
/**
* Send the packet directly over udp.
*
* Can't be larger than 1200 bytes
*/
Unreliable = 0,
/**
* Like `Unreliable` but doesn't buffer packets
* sent before the connection has started.
*/
UnreliableNoDelay = 1,
/**
* Reliable packet sending.
*
* Can't be larger than 1 megabyte.
*/
Reliable = 2,
/**
* Like `Reliable` but applies the nagle
* algorithm to packets being sent
*/
ReliableWithBuffering = 3,
}
export function sendP2PPacket(
steamId64: bigint,
sendType: SendType,
data: Buffer
): boolean;
export function isP2PPacketAvailable(): number;
export function readP2PPacket(size: number): P2PPacket;
export function acceptP2PSession(steamId64: bigint): void;
}
export namespace overlay {
export const enum Dialog {
Friends = 0,
Community = 1,
Players = 2,
Settings = 3,
OfficialGameGroup = 4,
Stats = 5,
Achievements = 6,
}
export const enum StoreFlag {
None = 0,
AddToCart = 1,
AddToCartAndShow = 2,
}
export function activateDialog(dialog: Dialog): void;
export function activateDialogToUser(
dialog: Dialog,
steamId64: bigint
): void;
export function activateInviteDialog(lobbyId: bigint): void;
export function activateToWebPage(url: string): void;
export function activateToStore(appId: number, flag: StoreFlag): void;
}
export namespace stats {
export function getInt(name: string): number | null;
export function setInt(name: string, value: number): boolean;
export function store(): boolean;
export function resetAll(achievementsToo: boolean): boolean;
}
export namespace utils {
export function getAppId(): number;
export function getServerRealTime(): number;
export function isSteamRunningOnSteamDeck(): boolean;
}
export namespace workshop {
export interface UgcResult {
itemId: bigint;
needsToAcceptAgreement: boolean;
}
export const enum UgcItemVisibility {
Public = 0,
FriendsOnly = 1,
Private = 2,
Unlisted = 3,
}
export interface UgcUpdate {
title?: string;
description?: string;
changeNote?: string;
previewPath?: string;
contentPath?: string;
tags?: Array<string>;
visibility?: UgcItemVisibility;
}
export interface InstallInfo {
folder: string;
sizeOnDisk: bigint;
timestamp: number;
}
export interface DownloadInfo {
current: bigint;
total: bigint;
}
export function createItem(
appId?: number | undefined | null
): Promise<UgcResult>;
export function updateItem(
itemId: bigint,
updateDetails: UgcUpdate,
appId?: number | undefined | null
): Promise<UgcResult>;
/**
* Subscribe to a workshop item. It will be downloaded and installed as soon as possible.
*
* {@link https://partner.steamgames.com/doc/api/ISteamUGC#SubscribeItem}
*/
export function subscribe(itemId: bigint): Promise<void>;
/**
* Unsubscribe from a workshop item. This will result in the item being removed after the game quits.
*
* {@link https://partner.steamgames.com/doc/api/ISteamUGC#UnsubscribeItem}
*/
export function unsubscribe(itemId: bigint): Promise<void>;
/**
* Gets the current state of a workshop item on this client. States can be combined.
*
* @returns a number with the current item state, e.g. 9
* 9 = 1 (The current user is subscribed to this item) + 8 (The item needs an update)
*
* {@link https://partner.steamgames.com/doc/api/ISteamUGC#GetItemState}
* {@link https://partner.steamgames.com/doc/api/ISteamUGC#EItemState}
*/
export function state(itemId: bigint): number;
/**
* Gets info about currently installed content on the disc for workshop item.
*
* @returns an object with the the properties {folder, size_on_disk, timestamp}
*
* {@link https://partner.steamgames.com/doc/api/ISteamUGC#GetItemInstallInfo}
*/
export function installInfo(itemId: bigint): InstallInfo | null;
/**
* Get info about a pending download of a workshop item.
*
* @returns an object with the properties {current, total}
*
* {@link https://partner.steamgames.com/doc/api/ISteamUGC#GetItemDownloadInfo}
*/
export function downloadInfo(itemId: bigint): DownloadInfo | null;
/**
* Download or update a workshop item.
*
* @param highPriority - If high priority is true, start the download in high priority mode, pausing any existing in-progress Steam downloads and immediately begin downloading this workshop item.
* @returns true or false
*
* {@link https://partner.steamgames.com/doc/api/ISteamUGC#DownloadItem}
*/
export function download(itemId: bigint, highPriority: boolean): boolean;
}
}
declare module 'steamworks.js' {
export function init(appId?: number): Client;
export function restartAppIfNecessary(appId: number): boolean;
export function electronEnableSteamOverlay(
disableEachFrameInvalidation?: boolean
): void;
export type Client = Omit<
typeof import('steamworks.js/client'),
'init' | 'runCallbacks'
>;
export const SteamCallback: typeof import('steamworks.js/client').callback.SteamCallback;
}

View File

@@ -1,20 +1,23 @@
cmake_minimum_required(VERSION 2.6)
cmake_policy(SET CMP0015 NEW)
cmake_minimum_required(VERSION 3.5)
project(SystemInfo)
gd_add_extension_includes()
#Defines
###
# Defines
#
gd_add_extension_definitions(SystemInfo)
#The targets
###
# The targets
#
include_directories(.)
file(GLOB source_files *.cpp *.h)
file(
GLOB
source_files
*.cpp
*.h)
gd_add_clang_utils(SystemInfo "${source_files}")
gd_add_extension_target(SystemInfo "${source_files}")
#Linker files for the IDE extension
###
# Linker files for the IDE extension
#
gd_extension_link_libraries(SystemInfo)

View File

@@ -25,27 +25,21 @@ class SystemInfoJsExtension : public gd::PlatformExtension {
DeclareSystemInfoExtension(*this);
GetAllConditions()["SystemInfo::IsMobile"]
.codeExtraInformation
.SetIncludeFile("Extensions/SystemInfo/systeminfotools.js")
.SetFunctionName("gdjs.evtTools.systemInfo.isMobile");
GetAllConditions()["SystemInfo::IsNativeMobileApp"]
.codeExtraInformation
.SetIncludeFile("Extensions/SystemInfo/systeminfotools.js")
.SetFunctionName("gdjs.evtTools.systemInfo.isNativeMobileApp");
GetAllConditions()["SystemInfo::IsNativeDesktopApp"]
.codeExtraInformation
.SetIncludeFile("Extensions/SystemInfo/systeminfotools.js")
.SetFunctionName("gdjs.evtTools.systemInfo.isNativeDesktopApp");
GetAllConditions()["SystemInfo::IsWebGLSupported"]
.codeExtraInformation
.SetIncludeFile("Extensions/SystemInfo/systeminfotools.js")
.SetFunctionName("gdjs.evtTools.systemInfo.isWebGLSupported");
GetAllConditions()["SystemInfo::IsPreview"]
.codeExtraInformation
.SetIncludeFile("Extensions/SystemInfo/systeminfotools.js")
.SetFunctionName("gdjs.evtTools.systemInfo.isPreview");
GetAllConditions()["SystemInfo::HasTouchScreen"]
.codeExtraInformation
.SetIncludeFile("Extensions/SystemInfo/systeminfotools.js")
.SetFunctionName("gdjs.evtTools.systemInfo.hasTouchScreen");

View File

@@ -1,20 +1,23 @@
cmake_minimum_required(VERSION 2.6)
cmake_policy(SET CMP0015 NEW)
cmake_minimum_required(VERSION 3.5)
project(TextEntryObject)
gd_add_extension_includes()
#Defines
###
# Defines
#
gd_add_extension_definitions(TextEntryObject)
#The targets
###
# The targets
#
include_directories(.)
file(GLOB source_files *.cpp *.h)
file(
GLOB
source_files
*.cpp
*.h)
gd_add_clang_utils(TextEntryObject "${source_files}")
gd_add_extension_target(TextEntryObject "${source_files}")
#Linker files for the IDE extension
###
# Linker files for the IDE extension
#
gd_extension_link_libraries(TextEntryObject)

View File

@@ -283,7 +283,7 @@ module.exports = {
textInputObject
)
.setCategoryFullName(_('User interface'))
.addUnsupportedBaseObjectCapability('effect')
.markBaseObjectCapabilityAsUnsupported('effect')
.setIncludeFile('Extensions/TextInput/textinputruntimeobject.js')
.addIncludeFile(
'Extensions/TextInput/textinputruntimeobject-pixi-renderer.js'

View File

@@ -1,20 +1,23 @@
cmake_minimum_required(VERSION 2.6)
cmake_policy(SET CMP0015 NEW)
cmake_minimum_required(VERSION 3.5)
project(TextObject)
gd_add_extension_includes()
#Defines
###
# Defines
#
gd_add_extension_definitions(TextObject)
#The targets
###
# The targets
#
include_directories(.)
file(GLOB source_files *.cpp *.h)
file(
GLOB
source_files
*.cpp
*.h)
gd_add_clang_utils(TextObject "${source_files}")
gd_add_extension_target(TextObject "${source_files}")
#Linker files for the IDE extension
###
# Linker files for the IDE extension
#
gd_extension_link_libraries(TextObject)

View File

@@ -78,6 +78,7 @@ void DeclareTextObjectExtension(gd::PlatformExtension& extension) {
.AddParameter("police", _("Font"))
.SetFunctionName("ChangeFont");
// Deprecated
obj.AddCondition("ScaleX",
_("Scale on X axis"),
_("Compare the scale of the text on the X axis"),
@@ -91,8 +92,10 @@ void DeclareTextObjectExtension(gd::PlatformExtension& extension) {
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Scale to compare to (1 by default)")))
.SetHidden()
.SetFunctionName("GetScaleX");
// Deprecated
obj.AddAction(
"ScaleX",
_("Scale on X axis"),
@@ -107,8 +110,10 @@ void DeclareTextObjectExtension(gd::PlatformExtension& extension) {
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Scale (1 by default)")))
.SetHidden()
.SetFunctionName("SetScaleX");
// Deprecated
obj.AddCondition("ScaleY",
_("Scale on Y axis"),
_("Compare the scale of the text on the Y axis"),
@@ -122,8 +127,10 @@ void DeclareTextObjectExtension(gd::PlatformExtension& extension) {
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Scale to compare to (1 by default)")))
.SetHidden()
.SetFunctionName("GetScaleY");
// Deprecated
obj.AddAction(
"ScaleY",
_("Scale on Y axis"),
@@ -138,8 +145,10 @@ void DeclareTextObjectExtension(gd::PlatformExtension& extension) {
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Scale (1 by default)")))
.SetHidden()
.SetFunctionName("SetScaleY");
// Deprecated
obj.AddAction(
"Scale",
_("Scale"),
@@ -154,6 +163,7 @@ void DeclareTextObjectExtension(gd::PlatformExtension& extension) {
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Scale (1 by default)")))
.SetHidden()
.SetFunctionName("SetScale");
obj.AddAction(
@@ -497,20 +507,24 @@ void DeclareTextObjectExtension(gd::PlatformExtension& extension) {
"res/actions/textPadding_black.png")
.AddParameter("object", _("Object"), "Text");
// Deprecated
obj.AddExpression("ScaleX",
_("X Scale of a Text object"),
_("X Scale of a Text object"),
_("Scale"),
"res/actions/scaleWidth_black.png")
.AddParameter("object", _("Object"), "Text")
.SetHidden()
.SetFunctionName("GetScaleX");
// Deprecated
obj.AddExpression("ScaleY",
_("Y Scale of a Text object"),
_("Y Scale of a Text object"),
_("Scale"),
"res/actions/scaleHeight_black.png")
.AddParameter("object", _("Object"), "Text")
.SetHidden()
.SetFunctionName("GetScaleY");
obj.AddExpression("Opacity",

View File

@@ -205,6 +205,8 @@ const defineTileMap = function (
objectTileMap
)
.setCategoryFullName(_('Advanced'))
.markBaseObjectCapabilityAsSupported("resizable")
.markBaseObjectCapabilityAsSupported("scalable")
.setIncludeFile('Extensions/TileMap/tilemapruntimeobject.js')
.addIncludeFile('Extensions/TileMap/TileMapRuntimeManager.js')
.addIncludeFile('Extensions/TileMap/tilemapruntimeobject-pixi-renderer.js')
@@ -495,6 +497,7 @@ const defineTileMap = function (
.getCodeExtraInformation()
.setFunctionName('getAnimationFps');
// Deprecated
object
.addAction(
'Scale',
@@ -513,10 +516,12 @@ const defineTileMap = function (
)
)
.markAsAdvanced()
.setHidden()
.getCodeExtraInformation()
.setFunctionName('setScale')
.setGetter('getScale');
// Deprecated
object
.addExpressionAndConditionAndAction(
'number',
@@ -535,9 +540,11 @@ const defineTileMap = function (
)
)
.markAsAdvanced()
.setHidden()
.setFunctionName('setScaleX')
.setGetter('getScaleX');
// Deprecated
object
.addExpressionAndConditionAndAction(
'number',
@@ -556,9 +563,11 @@ const defineTileMap = function (
)
)
.markAsAdvanced()
.setHidden()
.setFunctionName('setScaleY')
.setGetter('getScaleY');
// Deprecated
object
.addAction(
'Width',
@@ -575,9 +584,11 @@ const defineTileMap = function (
gd.ParameterOptions.makeNewOptions()
)
.markAsAdvanced()
.setHidden()
.getCodeExtraInformation()
.setFunctionName('setWidth');
// Deprecated
object
.addAction(
'Height',
@@ -594,6 +605,7 @@ const defineTileMap = function (
gd.ParameterOptions.makeNewOptions()
)
.markAsAdvanced()
.setHidden()
.getCodeExtraInformation()
.setFunctionName('setHeight');
};
@@ -789,6 +801,8 @@ const defineCollisionMask = function (
collisionMaskObject
)
.setCategoryFullName(_('Advanced'))
.markBaseObjectCapabilityAsSupported("resizable")
.markBaseObjectCapabilityAsSupported("scalable")
.setIncludeFile('Extensions/TileMap/tilemapcollisionmaskruntimeobject.js')
.addIncludeFile('Extensions/TileMap/TileMapRuntimeManager.js')
.addIncludeFile('Extensions/TileMap/pako/dist/pako.min.js')
@@ -909,6 +923,7 @@ const defineCollisionMask = function (
.setFunctionName('setScale')
.setGetter('getScale');
// Deprecated
object
.addExpressionAndConditionAndAction(
'number',
@@ -932,9 +947,11 @@ const defineCollisionMask = function (
)
)
.markAsAdvanced()
.setHidden()
.setFunctionName('setScaleX')
.setGetter('getScaleX');
// Deprecated
object
.addExpressionAndConditionAndAction(
'number',
@@ -958,9 +975,11 @@ const defineCollisionMask = function (
)
)
.markAsAdvanced()
.setHidden()
.setFunctionName('setScaleY')
.setGetter('getScaleY');
// Deprecated
object
.addScopedAction(
'Width',
@@ -982,9 +1001,11 @@ const defineCollisionMask = function (
gd.ParameterOptions.makeNewOptions()
)
.markAsAdvanced()
.setHidden()
.getCodeExtraInformation()
.setFunctionName('setWidth');
// Deprecated
object
.addScopedAction(
'Height',
@@ -1006,6 +1027,7 @@ const defineCollisionMask = function (
gd.ParameterOptions.makeNewOptions()
)
.markAsAdvanced()
.setHidden()
.getCodeExtraInformation()
.setFunctionName('setHeight');
};

File diff suppressed because one or more lines are too long

View File

@@ -1,20 +1,23 @@
cmake_minimum_required(VERSION 2.6)
cmake_policy(SET CMP0015 NEW)
cmake_minimum_required(VERSION 3.5)
project(TiledSpriteObject)
gd_add_extension_includes()
#Defines
###
# Defines
#
gd_add_extension_definitions(TiledSpriteObject)
#The targets
###
# The targets
#
include_directories(.)
file(GLOB source_files *.cpp *.h)
file(
GLOB
source_files
*.cpp
*.h)
gd_add_clang_utils(TiledSpriteObject "${source_files}")
gd_add_extension_target(TiledSpriteObject "${source_files}")
#Linker files for the IDE extension
###
# Linker files for the IDE extension
#
gd_extension_link_libraries(TiledSpriteObject)

View File

@@ -34,6 +34,7 @@ void DeclareTiledSpriteObjectExtension(gd::PlatformExtension& extension) {
_("Tiled Sprite"),
_("Displays an image repeated over an area."),
"CppPlatform/Extensions/TiledSpriteIcon.png")
.MarkBaseObjectCapabilityAsSupported("resizable")
.SetCategoryFullName(_("General"));
obj.AddCondition("Opacity",
@@ -86,6 +87,7 @@ void DeclareTiledSpriteObjectExtension(gd::PlatformExtension& extension) {
.AddParameter("object", _("Object"), "TiledSprite")
.AddParameter("color", _("Tint"));
// Deprecated
obj.AddAction("Width",
_("Width"),
_("Modify the width of a Tiled Sprite."),
@@ -97,9 +99,11 @@ void DeclareTiledSpriteObjectExtension(gd::PlatformExtension& extension) {
.AddParameter("object", _("Object"), "TiledSprite")
.UseStandardOperatorParameters("number",
gd::ParameterOptions::MakeNewOptions())
.SetHidden()
.SetFunctionName("SetWidth")
.SetGetter("GetWidth");
// Deprecated
obj.AddCondition("Width",
_("Width"),
_("Test the width of a Tiled Sprite."),
@@ -111,8 +115,10 @@ void DeclareTiledSpriteObjectExtension(gd::PlatformExtension& extension) {
.UseStandardRelationalOperatorParameters(
"number", gd::ParameterOptions::MakeNewOptions())
.MarkAsAdvanced()
.SetHidden()
.SetFunctionName("GetWidth");
// Deprecated
obj.AddAction("Height",
_("Height"),
_("Modify the height of a Tiled Sprite."),
@@ -124,9 +130,11 @@ void DeclareTiledSpriteObjectExtension(gd::PlatformExtension& extension) {
.AddParameter("object", _("Object"), "TiledSprite")
.UseStandardOperatorParameters("number",
gd::ParameterOptions::MakeNewOptions())
.SetHidden()
.SetFunctionName("SetHeight")
.SetGetter("GetHeight");
// Deprecated
obj.AddCondition("Height",
_("Height"),
_("Test the height of a Tiled Sprite."),
@@ -138,8 +146,10 @@ void DeclareTiledSpriteObjectExtension(gd::PlatformExtension& extension) {
.UseStandardRelationalOperatorParameters(
"number", gd::ParameterOptions::MakeNewOptions())
.MarkAsAdvanced()
.SetHidden()
.SetFunctionName("GetHeight");
// Deprecated
obj.AddAction("SetSize",
_("Size"),
_("Modify the size of a Tiled Sprite."),
@@ -151,6 +161,7 @@ void DeclareTiledSpriteObjectExtension(gd::PlatformExtension& extension) {
.AddParameter("object", _("Object"), "TiledSprite")
.AddParameter("expression", _("Width"))
.AddParameter("expression", _("Height"))
.SetHidden()
.SetFunctionName("SetSize");
// Deprecated: now available for all objects.

View File

@@ -1,20 +1,23 @@
cmake_minimum_required(VERSION 2.6)
cmake_policy(SET CMP0015 NEW)
cmake_minimum_required(VERSION 3.5)
project(TopDownMovementBehavior)
gd_add_extension_includes()
#Defines
###
# Defines
#
gd_add_extension_definitions(TopDownMovementBehavior)
#The targets
###
# The targets
#
include_directories(.)
file(GLOB source_files *.cpp *.h)
file(
GLOB
source_files
*.cpp
*.h)
gd_add_clang_utils(TopDownMovementBehavior "${source_files}")
gd_add_extension_target(TopDownMovementBehavior "${source_files}")
#Linker files for the IDE extension
###
# Linker files for the IDE extension
#
gd_extension_link_libraries(TopDownMovementBehavior)

View File

@@ -1,75 +1,88 @@
cmake_minimum_required(VERSION 2.6)
cmake_policy(SET CMP0015 NEW)
cmake_minimum_required(VERSION 3.5)
project(GDJS)
#Dependencies on external libraries:
###
# Dependencies on external libraries:
#
include_directories(${GDCORE_include_dir})
#Defines
###
add_definitions( -DGD_IDE_ONLY )
IF (EMSCRIPTEN)
add_definitions( -DEMSCRIPTEN )
ENDIF()
IF(CMAKE_BUILD_TYPE MATCHES "Debug")
add_definitions( -DDEBUG )
ELSE()
add_definitions( -DRELEASE )
ENDIF()
# Defines
#
add_definitions(-DGD_IDE_ONLY)
if(EMSCRIPTEN)
add_definitions(-DEMSCRIPTEN)
endif()
if("${CMAKE_BUILD_TYPE}" MATCHES "Debug")
add_definitions(-DDEBUG)
else()
add_definitions(-DRELEASE)
endif()
IF(WIN32)
add_definitions( -DWINDOWS )
add_definitions( "-DGD_API=__declspec(dllexport)" )
add_definitions( "-DGD_CORE_API=__declspec( dllimport )" )
add_definitions( -D__GNUWIN32__ )
ELSE()
IF(APPLE)
add_definitions( -DMACOS )
ELSE()
add_definitions( -DLINUX )
ENDIF()
add_definitions( -DGD_API= )
add_definitions( -DGD_CORE_API= )
ENDIF(WIN32)
if(WIN32)
add_definitions(-DWINDOWS)
add_definitions("-DGD_API=__declspec(dllexport)")
add_definitions("-DGD_CORE_API=__declspec(dllimport)")
add_definitions(-D__GNUWIN32__)
else()
if(APPLE)
add_definitions(-DMACOS)
else()
add_definitions(-DLINUX)
endif()
add_definitions(-DGD_API=)
add_definitions(-DGD_CORE_API=)
endif()
#The target
###
# The target
#
include_directories(.)
file(GLOB f1 GDJS/* GDJS/IDE/* GDJS/IDE/mongoose/*)
file(GLOB_RECURSE f2 GDJS/Extensions/* GDJS/Events/*)
file(
GLOB
f1
GDJS/*
GDJS/IDE/*
GDJS/IDE/mongoose/*)
file(
GLOB_RECURSE
f2
GDJS/Extensions/*
GDJS/Events/*)
set(source_files ${f1} ${f2})
IF(NOT EMSCRIPTEN)
file(GLOB_RECURSE f3 GDJS/IDE/Dialogs/*)
set(source_files ${source_files} ${f3})
ENDIF()
if(NOT EMSCRIPTEN)
file(
GLOB_RECURSE
f3
GDJS/IDE/Dialogs/*)
set(source_files ${source_files} ${f3})
endif()
file(GLOB_RECURSE formatted_source_files GDJS/Events/* GDJS/Extensions/* GDJS/IDE/*)
file(
GLOB_RECURSE
formatted_source_files
GDJS/Events/*
GDJS/Extensions/*
GDJS/IDE/*)
gd_add_clang_utils(GDJS "${formatted_source_files}")
IF(EMSCRIPTEN)
if(EMSCRIPTEN)
# Emscripten treats all libraries as static libraries
add_library(GDJS STATIC ${source_files})
ELSE()
else()
add_library(GDJS SHARED ${source_files})
ENDIF()
IF(EMSCRIPTEN)
endif()
if(EMSCRIPTEN)
set_target_properties(GDJS PROPERTIES SUFFIX ".bc")
ELSEIF(WIN32)
elseif(WIN32)
set_target_properties(GDJS PROPERTIES PREFIX "")
ELSE()
else()
set_target_properties(GDJS PROPERTIES PREFIX "lib")
ENDIF()
endif()
set_target_properties(GDJS PROPERTIES MACOS_RPATH "..")
set(LIBRARY_OUTPUT_PATH ${GD_base_dir}/Binaries/Output/${CMAKE_BUILD_TYPE}_${CMAKE_SYSTEM_NAME}/JsPlatform)
set(ARCHIVE_OUTPUT_PATH ${GD_base_dir}/Binaries/Output/${CMAKE_BUILD_TYPE}_${CMAKE_SYSTEM_NAME}/JsPlatform)
set(RUNTIME_OUTPUT_PATH ${GD_base_dir}/Binaries/Output/${CMAKE_BUILD_TYPE}_${CMAKE_SYSTEM_NAME}/JsPlatform)
#Linker files
###
IF(EMSCRIPTEN)
#Nothing.
ELSE()
# Linker files
#
if(NOT EMSCRIPTEN)
target_link_libraries(GDJS GDCore)
ENDIF()
endif()

View File

@@ -50,6 +50,12 @@ class JsCodeEvent : public gd::BaseEvent {
bool IsEventsSheetExpanded() const { return eventsSheetExpanded; }
void SetEventsSheetExpanded(bool enable) { eventsSheetExpanded = enable; };
std::vector<gd::Expression*> GetAllObjectExpressions() {
std::vector<gd::Expression*> allObjectExpressions;
allObjectExpressions.push_back(&parameterObjects);
return allObjectExpressions;
}
private:
void Init(const JsCodeEvent& event);

View File

@@ -19,6 +19,7 @@ gd::String BehaviorCodeGenerator::GenerateRuntimeBehaviorCompleteCode(
const std::map<gd::String, gd::String>& behaviorMethodMangledNames,
std::set<gd::String>& includeFiles,
bool compilationForRuntime) {
std::cout << "GenerateRuntimeBehaviorCompleteCode" << std::endl;
auto& eventsFunctionsVector =
eventsBasedBehavior.GetEventsFunctions().GetInternalVector();

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,324 @@
/*
* GDevelop Core
* Copyright 2008-2023 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#pragma once
#include "GDCore/String.h"
#include <functional>
#include <map>
#include <memory>
#include <vector>
namespace gd {
class PlatformExtension;
class Project;
class EventsFunctionsExtension;
class EventsBasedBehavior;
class BehaviorMetadata;
class EventsBasedObject;
class ObjectMetadata;
class EventsFunction;
class PropertyDescriptor;
class EventsFunctionsContainer;
class AbstractFunctionMetadata;
class InstructionOrExpressionContainerMetadata;
class AbstractEventsBasedEntity;
class NamedPropertyDescriptor;
class ParameterMetadata;
class InstructionMetadata;
class ExpressionMetadata;
class MultipleInstructionMetadata;
} // namespace gd
namespace gdjs {
/**
* \brief This file contains the logic to declare extension metadata from
* events functions or events based behaviors.
* These are basically adapters from gd::EventsFunctionsExtension, and children,
* to a real extension declaration (like in `JsExtension.js` or `Extension.cpp`
* files).
*
* \ingroup IDE
*/
class MetadataDeclarationHelper {
public:
MetadataDeclarationHelper(){};
virtual ~MetadataDeclarationHelper(){};
gd::AbstractFunctionMetadata &GenerateFreeFunctionMetadata(
const gd::Project &project, gd::PlatformExtension &extension,
const gd::EventsFunctionsExtension &eventsFunctionsExtension,
const gd::EventsFunction &eventsFunction);
static gd::BehaviorMetadata &GenerateBehaviorMetadata(
const gd::Project &project, gd::PlatformExtension &extension,
const gd::EventsFunctionsExtension &eventsFunctionsExtension,
const gd::EventsBasedBehavior &eventsBasedBehavior,
std::map<gd::String, gd::String> &behaviorMethodMangledNames);
static gd::ObjectMetadata &GenerateObjectMetadata(
const gd::Project &project, gd::PlatformExtension &extension,
const gd::EventsFunctionsExtension &eventsFunctionsExtension,
const gd::EventsBasedObject &eventsBasedObject,
std::map<gd::String, gd::String> &objectMethodMangledNames);
static gd::String GetFreeFunctionCodeName(
const gd::EventsFunctionsExtension &eventsFunctionsExtension,
const gd::EventsFunction &eventsFunction);
/**
* Declare an extension from an events based extension.
*/
static void DeclareExtension(
gd::PlatformExtension &extension,
const gd::EventsFunctionsExtension &eventsFunctionsExtension);
/**
* Check if the name of the function is the name of a lifecycle function (for
* events-based behaviors), that will be called automatically by the game
* engine.
*/
static bool IsBehaviorLifecycleEventsFunction(const gd::String &functionName);
/**
* Check if the name of the function is the name of a lifecycle function (for
* events-based objects), that will be called automatically by the game
* engine.
*/
static bool IsObjectLifecycleEventsFunction(const gd::String &functionName);
/**
* Check if the name of the function is the name of a lifecycle function (for
* events-based extensions), that will be called automatically by the game
* engine.
*/
static bool
IsExtensionLifecycleEventsFunction(const gd::String &functionName);
static gd::String ShiftSentenceParamIndexes(const gd::String &sentence,
const int offset);
private:
static const gd::String &
GetExtensionIconUrl(gd::PlatformExtension &extension);
/**
* Declare the dependencies of an extension from an events based extension.
*/
static void DeclareExtensionDependencies(
gd::PlatformExtension &extension,
const gd::EventsFunctionsExtension &eventsFunctionsExtension);
static void DeclarePropertyInstructionAndExpression(
gd::PlatformExtension &extension,
gd::InstructionOrExpressionContainerMetadata &entityMetadata,
const gd::AbstractEventsBasedEntity &eventsBasedEntity,
const gd::NamedPropertyDescriptor &property,
const gd::String &propertyLabel, const gd::String &expressionName,
const gd::String &conditionName, const gd::String &actionName,
const gd::String &toggleActionName, const gd::String &setterName,
const gd::String &getterName, const gd::String &toggleFunctionName,
const int valueParameterIndex,
std::function<gd::AbstractFunctionMetadata &(
gd::AbstractFunctionMetadata &instructionOrExpression)>
addObjectAndBehaviorParameters);
/**
* Declare the instructions (actions/conditions) and expressions for the
* properties of the given events based behavior.
* This is akin to what would happen by manually declaring a JS extension
* (see `JsExtension.js` files of extensions).
*/
static void DeclareBehaviorPropertiesInstructionAndExpressions(
gd::PlatformExtension &extension, gd::BehaviorMetadata &behaviorMetadata,
const gd::EventsBasedBehavior &eventsBasedBehavior);
/**
* Declare the instructions (actions/conditions) and expressions for the
* properties of the given events based object.
* This is akin to what would happen by manually declaring a JS extension
* (see `JsExtension.js` files of extensions).
*/
static void DeclareObjectPropertiesInstructionAndExpressions(
gd::PlatformExtension &extension, gd::ObjectMetadata &objectMetadata,
const gd::EventsBasedObject &eventsBasedObject);
/**
* Declare the instructions (actions/conditions) and expressions for the
* properties of the given events based object.
* This is akin to what would happen by manually declaring a JS extension
* (see `JsExtension.js` files of extensions).
*/
static void DeclareObjectInternalInstructions(
gd::PlatformExtension &extension, gd::ObjectMetadata &objectMetadata,
const gd::EventsBasedObject &eventsBasedObject);
static const gd::String defaultExtensionIconPath;
/**
* Declare the behavior for the given
* events based behavior.
*/
static gd::BehaviorMetadata &
DeclareBehaviorMetadata(gd::PlatformExtension &extension,
const gd::EventsBasedBehavior &eventsBasedBehavior);
/**
* Declare the object for the given
* events based object.
*/
static gd::ObjectMetadata &
DeclareObjectMetadata(gd::PlatformExtension &extension,
const gd::EventsBasedObject &eventsBasedObject);
static void
AddParameter(gd::AbstractFunctionMetadata &instructionOrExpression,
const gd::ParameterMetadata &parameter);
/**
* Declare the instruction (action/condition) or expression for the given
* (free) events function.
*/
gd::AbstractFunctionMetadata &DeclareInstructionOrExpressionMetadata(
gd::PlatformExtension &extension,
const gd::EventsFunctionsExtension &eventsFunctionsExtension,
const gd::EventsFunction &eventsFunction);
/**
* Declare the instruction (action/condition) or expression for the given
* (free) events function.
*/
gd::AbstractFunctionMetadata &DeclareExpressionMetadata(
gd::PlatformExtension &extension,
const gd::EventsFunctionsExtension &eventsFunctionsExtension,
const gd::EventsFunction &eventsFunction);
/**
* Declare the instruction (action/condition) or expression for the given
* (free) events function.
*/
static gd::InstructionMetadata &DeclareInstructionMetadata(
gd::PlatformExtension &extension,
const gd::EventsFunctionsExtension &eventsFunctionsExtension,
const gd::EventsFunction &eventsFunction);
/**
* Declare the instruction (action/condition) or expression for the given
* behavior events function.
*/
gd::AbstractFunctionMetadata &DeclareBehaviorInstructionOrExpressionMetadata(
gd::PlatformExtension &extension, gd::BehaviorMetadata &behaviorMetadata,
const gd::EventsBasedBehavior &eventsBasedBehavior,
const gd::EventsFunction &eventsFunction,
std::map<gd::String, gd::String> &objectMethodMangledNames);
/**
* Declare the instruction (action/condition) or expression for the given
* behavior events function.
*/
gd::AbstractFunctionMetadata &DeclareBehaviorExpressionMetadata(
gd::PlatformExtension &extension, gd::BehaviorMetadata &behaviorMetadata,
const gd::EventsBasedBehavior &eventsBasedBehavior,
const gd::EventsFunction &eventsFunction);
/**
* Declare the instruction (action/condition) or expression for the given
* behavior events function.
*/
static gd::InstructionMetadata &DeclareBehaviorInstructionMetadata(
gd::PlatformExtension &extension, gd::BehaviorMetadata &behaviorMetadata,
const gd::EventsBasedBehavior &eventsBasedBehavior,
const gd::EventsFunction &eventsFunction);
/**
* Declare the instruction (action/condition) or expression for the given
* object events function.
*/
gd::AbstractFunctionMetadata &DeclareObjectInstructionOrExpressionMetadata(
gd::PlatformExtension &extension, gd::ObjectMetadata &objectMetadata,
const gd::EventsBasedObject &eventsBasedObject,
const gd::EventsFunction &eventsFunction,
std::map<gd::String, gd::String> &objectMethodMangledNames);
/**
* Declare the instruction (action/condition) or expression for the given
* object events function.
*/
gd::AbstractFunctionMetadata &DeclareObjectExpressionMetadata(
gd::PlatformExtension &extension, gd::ObjectMetadata &objectMetadata,
const gd::EventsBasedObject &eventsBasedObject,
const gd::EventsFunction &eventsFunction);
/**
* Declare the instruction (action/condition) or expression for the given
* object events function.
*/
static gd::InstructionMetadata &DeclareObjectInstructionMetadata(
gd::PlatformExtension &extension, gd::ObjectMetadata &objectMetadata,
const gd::EventsBasedObject &eventsBasedObject,
const gd::EventsFunction &eventsFunction);
/**
* Add to the instruction (action/condition) or expression the parameters
* expected by the events function.
*/
static void DeclareEventsFunctionParameters(
const gd::EventsFunctionsContainer &eventsFunctionsContainer,
const gd::EventsFunction &eventsFunction,
gd::ExpressionMetadata &expression,
const int userDefinedFirstParameterIndex);
/**
* Add to the instruction (action/condition) or expression the parameters
* expected by the events function.
*/
static void DeclareEventsFunctionParameters(
const gd::EventsFunctionsContainer &eventsFunctionsContainer,
const gd::EventsFunction &eventsFunction,
gd::InstructionMetadata &instruction,
const int userDefinedFirstParameterIndex);
/**
* Add to the instruction (action/condition) or expression the parameters
* expected by the events function.
*/
static void DeclareEventsFunctionParameters(
const gd::EventsFunctionsContainer &eventsFunctionsContainer,
const gd::EventsFunction &eventsFunction,
gd::MultipleInstructionMetadata &multipleInstructionMetadata,
const int userDefinedFirstParameterIndex);
static gd::String GetExtensionCodeNamespacePrefix(
const gd::EventsFunctionsExtension eventsFunctionsExtension);
/** Generate the namespace for a free function. */
static gd::String
GetFreeFunctionCodeNamespace(const gd::EventsFunction &eventsFunction,
const gd::String &codeNamespacePrefix);
/** Generate the namespace for a behavior function. */
static gd::String GetBehaviorFunctionCodeNamespace(
const gd::EventsBasedBehavior &eventsBasedBehavior,
const gd::String &codeNamespacePrefix);
/** Generate the namespace for an object function. */
static gd::String
GetObjectFunctionCodeNamespace(const gd::EventsBasedObject &eventsBasedObject,
const gd::String &codeNamespacePrefix);
static gd::String RemoveTrailingDot(const gd::String &description);
static gd::String
GetStringifiedExtraInfo(const gd::PropertyDescriptor &property);
static gd::String CapitalizeFirstLetter(const gd::String &string);
static gd::String UncapitalizeFirstLetter(const gd::String &string);
std::vector<gd::MultipleInstructionMetadata> expressionAndConditions;
};
} // namespace gdjs

View File

@@ -18,7 +18,6 @@ AdvancedExtension::AdvancedExtension() {
gd::BuiltinExtensionsImplementer::ImplementsAdvancedExtension(*this);
GetAllActions()["SetReturnNumber"]
.GetCodeExtraInformation()
.SetCustomCodeGenerator([](gd::Instruction& instruction,
gd::EventsCodeGenerator& codeGenerator,
gd::EventsCodeGenerationContext& context) {
@@ -35,7 +34,6 @@ AdvancedExtension::AdvancedExtension() {
});
GetAllActions()["SetReturnString"]
.GetCodeExtraInformation()
.SetCustomCodeGenerator([](gd::Instruction& instruction,
gd::EventsCodeGenerator& codeGenerator,
gd::EventsCodeGenerationContext& context) {
@@ -52,7 +50,6 @@ AdvancedExtension::AdvancedExtension() {
});
GetAllActions()["SetReturnBoolean"]
.GetCodeExtraInformation()
.SetCustomCodeGenerator([](gd::Instruction& instruction,
gd::EventsCodeGenerator& codeGenerator,
gd::EventsCodeGenerationContext& context) {
@@ -67,7 +64,6 @@ AdvancedExtension::AdvancedExtension() {
});
GetAllActions()["CopyArgumentToVariable"]
.GetCodeExtraInformation()
.SetCustomCodeGenerator([](gd::Instruction &instruction,
gd::EventsCodeGenerator &codeGenerator,
gd::EventsCodeGenerationContext &context) {
@@ -86,7 +82,6 @@ AdvancedExtension::AdvancedExtension() {
});
GetAllActions()["CopyVariableToArgument"]
.GetCodeExtraInformation()
.SetCustomCodeGenerator([](gd::Instruction &instruction,
gd::EventsCodeGenerator &codeGenerator,
gd::EventsCodeGenerationContext &context) {
@@ -105,7 +100,6 @@ AdvancedExtension::AdvancedExtension() {
});
GetAllConditions()["GetArgumentAsBoolean"]
.GetCodeExtraInformation()
.SetCustomCodeGenerator([](gd::Instruction& instruction,
gd::EventsCodeGenerator& codeGenerator,
gd::EventsCodeGenerationContext& context) {
@@ -161,7 +155,6 @@ AdvancedExtension::AdvancedExtension() {
});
GetAllConditions()["CompareArgumentAsNumber"]
.GetCodeExtraInformation()
.SetCustomCodeGenerator([](gd::Instruction &instruction,
gd::EventsCodeGenerator &codeGenerator,
gd::EventsCodeGenerationContext &context) {
@@ -188,7 +181,6 @@ AdvancedExtension::AdvancedExtension() {
});
GetAllConditions()["CompareArgumentAsString"]
.GetCodeExtraInformation()
.SetCustomCodeGenerator([](gd::Instruction &instruction,
gd::EventsCodeGenerator &codeGenerator,
gd::EventsCodeGenerationContext &context) {

View File

@@ -27,14 +27,8 @@ BaseObjectExtension::BaseObjectExtension() {
std::map<gd::String, gd::ExpressionMetadata> &objectStrExpressions =
GetAllStrExpressionsForObject("");
objectActions["MettreX"]
.SetFunctionName("setX")
.SetGetter("getX")
.SetIncludeFile("runtimeobject.js");
objectActions["MettreY"]
.SetFunctionName("setY")
.SetGetter("getY")
.SetIncludeFile("runtimeobject.js");
objectActions["MettreX"].SetFunctionName("setX").SetGetter("getX");
objectActions["MettreY"].SetFunctionName("setY").SetGetter("getY");
objectConditions["PosX"].SetFunctionName("getX").SetIncludeFile(
"runtimeobject.js");
objectConditions["PosY"].SetFunctionName("getY").SetIncludeFile(
@@ -47,13 +41,8 @@ BaseObjectExtension::BaseObjectExtension() {
objectActions["SetCenterY"]
.SetFunctionName("setCenterYInScene")
.SetGetter("getCenterYInScene");
objectActions["SetAngle"]
.SetFunctionName("setAngle")
.SetGetter("getAngle")
.SetIncludeFile("runtimeobject.js");
objectConditions["Angle"]
.SetFunctionName("getAngle")
.SetIncludeFile("runtimeobject.js");
objectActions["SetAngle"].SetFunctionName("setAngle").SetGetter("getAngle");
objectConditions["Angle"].SetFunctionName("getAngle");
objectConditions["BoundingBoxLeft"].SetFunctionName("getAABBLeft");
objectConditions["BoundingBoxTop"].SetFunctionName("getAABBTop");
objectConditions["BoundingBoxRight"].SetFunctionName("getAABBRight");
@@ -62,144 +51,71 @@ BaseObjectExtension::BaseObjectExtension() {
objectConditions["BoundingBoxCenterY"].SetFunctionName("getAABBCenterY");
objectActions["Rotate"].SetFunctionName("rotate").SetIncludeFile(
"runtimeobject.js");
objectActions["RotateTowardAngle"]
.SetFunctionName("rotateTowardAngle")
.SetIncludeFile("runtimeobject.js");
objectActions["RotateTowardPosition"]
.SetFunctionName("rotateTowardPosition")
.SetIncludeFile("runtimeobject.js");
objectActions["ChangeLayer"]
.SetFunctionName("setLayer")
.SetIncludeFile("runtimeobject.js");
objectConditions["Layer"]
.SetFunctionName("isOnLayer")
.SetIncludeFile("runtimeobject.js");
objectActions["RotateTowardAngle"].SetFunctionName("rotateTowardAngle");
objectActions["RotateTowardPosition"].SetFunctionName("rotateTowardPosition");
objectActions["ChangeLayer"].SetFunctionName("setLayer");
objectConditions["Layer"].SetFunctionName("isOnLayer");
objectActions["ChangePlan"]
.SetFunctionName("setZOrder")
.SetGetter("getZOrder")
.SetIncludeFile("runtimeobject.js");
objectConditions["Plan"]
.SetFunctionName("getZOrder")
.SetIncludeFile("runtimeobject.js");
.SetGetter("getZOrder");
objectConditions["Plan"].SetFunctionName("getZOrder");
objectActions["Cache"].SetFunctionName("hide").SetIncludeFile(
"runtimeobject.js");
objectActions["Montre"].SetFunctionName("hide").SetIncludeFile(
"runtimeobject.js");
objectConditions["Visible"]
.SetFunctionName("isVisible")
.SetIncludeFile("runtimeobject.js");
objectConditions["Invisible"]
.SetFunctionName("isHidden")
.SetIncludeFile("runtimeobject.js");
objectConditions["IsEffectEnabled"]
.SetFunctionName("isEffectEnabled")
.SetIncludeFile("runtimeobject.js");
objectConditions["Visible"].SetFunctionName("isVisible");
objectConditions["Invisible"].SetFunctionName("isHidden");
objectConditions["IsEffectEnabled"].SetFunctionName("isEffectEnabled");
objectActions["Delete"].SetFunctionName("deleteFromScene");
objectActions["MettreAutourPos"].SetFunctionName("putAround");
objectActions["MettreAutour"]
.SetFunctionName("putAroundObject")
.SetIncludeFile("runtimeobject.js");
objectConditions["VarObjet"]
.SetFunctionName("getVariableNumber")
.SetIncludeFile("runtimeobject.js");
objectConditions["VarObjetTxt"]
.SetFunctionName("getVariableString")
.SetIncludeFile("runtimeobject.js");
objectConditions["ObjectVariableAsBoolean"]
.SetFunctionName("getVariableBoolean")
.SetIncludeFile("runtimeobject.js");
objectConditions["VarObjetDef"]
.SetFunctionName("hasVariable")
.SetIncludeFile("runtimeobject.js");
objectActions["AddForceXY"]
.SetFunctionName("addForce")
.SetIncludeFile("runtimeobject.js");
objectActions["AddForceAL"]
.SetFunctionName("addPolarForce")
.SetIncludeFile("runtimeobject.js");
objectActions["AddForceVersPos"]
.SetFunctionName("addForceTowardPosition")
.SetIncludeFile("runtimeobject.js");
objectActions["AddForceVers"]
.SetFunctionName("addForceTowardObject")
.SetIncludeFile("runtimeobject.js");
objectActions["Arreter"]
.SetFunctionName("clearForces")
.SetIncludeFile("runtimeobject.js");
objectConditions["Arret"]
.SetFunctionName("hasNoForces")
.SetIncludeFile("runtimeobject.js");
objectConditions["Vitesse"]
.SetFunctionName("getAverageForce().getLength")
.SetIncludeFile("runtimeobject.js");
objectConditions["AngleOfDisplacement"]
.SetFunctionName("averageForceAngleIs")
.SetIncludeFile("runtimeobject.js");
objectActions["SeparateFromObjects"]
.SetFunctionName("separateFromObjectsList")
.SetIncludeFile("runtimeobject.js");
objectActions["Ecarter"]
.codeExtraInformation // Deprecated
.SetFunctionName("separateObjectsWithoutForces")
.SetIncludeFile("runtimeobject.js");
objectActions["Rebondir"]
.codeExtraInformation // Deprecated
.SetFunctionName("separateObjectsWithForces")
.SetIncludeFile("runtimeobject.js");
objectConditions["BehaviorActivated"]
.SetFunctionName("behaviorActivated")
.SetIncludeFile("runtimeobject.js");
objectActions["ActivateBehavior"]
.SetFunctionName("activateBehavior")
.SetIncludeFile("runtimeobject.js");
objectConditions["ObjectVariableChildExists"]
.SetFunctionName("variableChildExists")
.SetIncludeFile("runtimeobject.js");
objectActions["ObjectVariableRemoveChild"]
.SetFunctionName("variableRemoveChild")
.SetIncludeFile("runtimeobject.js");
objectActions["ObjectVariableClearChildren"]
.SetFunctionName("variableClearChildren")
.SetIncludeFile("runtimeobject.js");
objectConditions["CollisionPoint"]
.SetFunctionName("isCollidingWithPoint")
.SetIncludeFile("runtimeobject.js");
objectConditions["ObjectTimer"] // deprecated
.SetFunctionName("timerElapsedTime")
.SetIncludeFile("runtimeobject.js");
objectConditions["CompareObjectTimer"]
.SetFunctionName("getTimerElapsedTimeInSecondsOrNaN")
.SetIncludeFile("runtimeobject.js");
objectConditions["ObjectTimerPaused"]
.SetFunctionName("timerPaused")
.SetIncludeFile("runtimeobject.js");
objectActions["ResetObjectTimer"]
.SetFunctionName("resetTimer")
.SetIncludeFile("runtimeobject.js");
objectActions["PauseObjectTimer"]
.SetFunctionName("pauseTimer")
.SetIncludeFile("runtimeobject.js");
objectActions["UnPauseObjectTimer"]
.SetFunctionName("unpauseTimer")
.SetIncludeFile("runtimeobject.js");
objectActions["RemoveObjectTimer"]
.SetFunctionName("removeTimer")
.SetIncludeFile("runtimeobject.js");
objectActions["EnableEffect"]
.SetFunctionName("enableEffect")
.SetIncludeFile("runtimeobject.js");
objectActions["SetEffectDoubleParameter"]
.SetFunctionName("setEffectDoubleParameter")
.SetIncludeFile("runtimeobject.js");
objectActions["SetEffectStringParameter"]
.SetFunctionName("setEffectStringParameter")
.SetIncludeFile("runtimeobject.js");
objectActions["SetEffectBooleanParameter"]
.SetFunctionName("setEffectBooleanParameter")
.SetIncludeFile("runtimeobject.js");
objectActions["SetIncludedInParentCollisionMask"]
.SetFunctionName("setIncludedInParentCollisionMask")
.SetIncludeFile("runtimeobject.js");
objectActions["MettreAutour"].SetFunctionName("putAroundObject");
objectConditions["VarObjet"].SetFunctionName("getVariableNumber");
objectConditions["VarObjetTxt"].SetFunctionName("getVariableString");
objectConditions["ObjectVariableAsBoolean"].SetFunctionName(
"getVariableBoolean");
objectConditions["VarObjetDef"].SetFunctionName("hasVariable");
objectActions["AddForceXY"].SetFunctionName("addForce");
objectActions["AddForceAL"].SetFunctionName("addPolarForce");
objectActions["AddForceVersPos"].SetFunctionName("addForceTowardPosition");
objectActions["AddForceVers"].SetFunctionName("addForceTowardObject");
objectActions["Arreter"].SetFunctionName("clearForces");
objectConditions["Arret"].SetFunctionName("hasNoForces");
objectConditions["Vitesse"].SetFunctionName("getAverageForce().getLength");
objectConditions["AngleOfDisplacement"].SetFunctionName(
"averageForceAngleIs");
objectActions["SeparateFromObjects"].SetFunctionName(
"separateFromObjectsList");
// Deprecated
objectActions["Ecarter"].SetFunctionName("separateObjectsWithoutForces");
// Deprecated
objectActions["Rebondir"].SetFunctionName("separateObjectsWithForces");
objectConditions["BehaviorActivated"].SetFunctionName("behaviorActivated");
objectActions["ActivateBehavior"].SetFunctionName("activateBehavior");
objectConditions["ObjectVariableChildExists"].SetFunctionName(
"variableChildExists");
objectActions["ObjectVariableRemoveChild"].SetFunctionName(
"variableRemoveChild");
objectActions["ObjectVariableClearChildren"].SetFunctionName(
"variableClearChildren");
objectConditions["CollisionPoint"].SetFunctionName("isCollidingWithPoint");
// deprecated
objectConditions["ObjectTimer"].SetFunctionName("timerElapsedTime");
objectConditions["CompareObjectTimer"].SetFunctionName(
"getTimerElapsedTimeInSecondsOrNaN");
objectConditions["ObjectTimerPaused"].SetFunctionName("timerPaused");
objectActions["ResetObjectTimer"].SetFunctionName("resetTimer");
objectActions["PauseObjectTimer"].SetFunctionName("pauseTimer");
objectActions["UnPauseObjectTimer"].SetFunctionName("unpauseTimer");
objectActions["RemoveObjectTimer"].SetFunctionName("removeTimer");
objectActions["EnableEffect"].SetFunctionName("enableEffect");
objectActions["SetEffectDoubleParameter"].SetFunctionName(
"setEffectDoubleParameter");
objectActions["SetEffectStringParameter"].SetFunctionName(
"setEffectStringParameter");
objectActions["SetEffectBooleanParameter"].SetFunctionName(
"setEffectBooleanParameter");
objectActions["SetIncludedInParentCollisionMask"].SetFunctionName(
"setIncludedInParentCollisionMask");
objectExpressions["X"].SetFunctionName("getX");
objectExpressions["Y"].SetFunctionName("getY");
@@ -212,11 +128,14 @@ BaseObjectExtension::BaseObjectExtension() {
objectExpressions["BoundingBoxCenterX"].SetFunctionName("getAABBCenterX");
objectExpressions["BoundingBoxCenterY"].SetFunctionName("getAABBCenterY");
objectExpressions["ZOrder"].SetFunctionName("getZOrder");
objectExpressions["Plan"].SetFunctionName("getZOrder"); // Deprecated
// Deprecated
objectExpressions["Plan"].SetFunctionName("getZOrder");
objectExpressions["Width"].SetFunctionName("getWidth");
objectExpressions["Height"].SetFunctionName("getHeight");
objectExpressions["Largeur"].SetFunctionName("getWidth"); // Deprecated
objectExpressions["Hauteur"].SetFunctionName("getHeight"); // Deprecated
// Deprecated
objectExpressions["Largeur"].SetFunctionName("getWidth");
// Deprecated
objectExpressions["Hauteur"].SetFunctionName("getHeight");
objectExpressions["Variable"]
.SetFunctionName("gdjs.RuntimeObject.getVariableNumber")
.SetStatic();
@@ -244,8 +163,8 @@ BaseObjectExtension::BaseObjectExtension() {
objectExpressions["Angle"].SetFunctionName("getAngle");
objectExpressions["ForceLength"].SetFunctionName(
"getAverageForce().getLength");
objectExpressions["Longueur"].SetFunctionName(
"getAverageForce().getLength"); // Deprecated
// Deprecated
objectExpressions["Longueur"].SetFunctionName("getAverageForce().getLength");
objectExpressions["Distance"].SetFunctionName("getDistanceToObject");
objectExpressions["SqDistance"].SetFunctionName("getSqDistanceToObject");
objectExpressions["DistanceToPosition"].SetFunctionName(
@@ -267,11 +186,12 @@ BaseObjectExtension::BaseObjectExtension() {
"gdjs.evtTools.object.createObjectOnScene");
GetAllActions()["CreateByName"].SetFunctionName(
"gdjs.evtTools.object.createObjectFromGroupOnScene");
// Deprecated
GetAllExpressions()["Count"].SetFunctionName(
"gdjs.evtTools.object.pickedObjectsCount"); // Deprecated
"gdjs.evtTools.object.pickedObjectsCount");
// Deprecated
GetAllConditions()["NbObjet"].SetFunctionName(
"gdjs.evtTools.object.pickedObjectsCount"); // Deprecated
"gdjs.evtTools.object.pickedObjectsCount");
GetAllExpressions()["SceneInstancesCount"].SetFunctionName(
"gdjs.evtTools.object.getSceneInstancesCount");
@@ -317,44 +237,71 @@ BaseObjectExtension::BaseObjectExtension() {
{"-", "sub"},
{"*", "mul"},
{"/", "div"},
})
.SetIncludeFile("runtimeobject.js");
});
objectActions["ModVarObjetTxt"]
.SetFunctionName("returnVariable")
.SetManipulatedType("string")
.SetMutators({
{"=", "setString"},
{"+", "concatenate"},
})
.SetIncludeFile("runtimeobject.js");
});
objectActions["SetObjectVariableAsBoolean"]
.SetFunctionName("setVariableBoolean")
.SetIncludeFile("runtimeobject.js");
objectActions["ToggleObjectVariableAsBoolean"]
.SetFunctionName("toggleVariableBoolean")
.SetIncludeFile("runtimeobject.js");
objectActions["SetObjectVariableAsBoolean"].SetFunctionName(
"setVariableBoolean");
objectActions["ToggleObjectVariableAsBoolean"].SetFunctionName(
"toggleVariableBoolean");
objectActions["ObjectVariablePush"]
.SetFunctionName("variablePushCopy")
.SetIncludeFile("runtimeobject.js");
objectActions["ObjectVariablePushString"]
.SetFunctionName("valuePush")
.SetIncludeFile("runtimeobject.js");
objectActions["ObjectVariablePushNumber"]
.SetFunctionName("valuePush")
.SetIncludeFile("runtimeobject.js");
objectActions["ObjectVariablePushBool"]
.SetFunctionName("valuePush")
.SetIncludeFile("runtimeobject.js");
objectActions["ObjectVariableRemoveAt"]
.SetFunctionName("variableRemoveAt")
.SetIncludeFile("runtimeobject.js");
objectConditions["ObjectVariableChildCount"]
.SetFunctionName("getVariableChildCount")
.SetIncludeFile("runtimeobject.js");
objectActions["ObjectVariablePush"].SetFunctionName("variablePushCopy");
objectActions["ObjectVariablePushString"].SetFunctionName("valuePush");
objectActions["ObjectVariablePushNumber"].SetFunctionName("valuePush");
objectActions["ObjectVariablePushBool"].SetFunctionName("valuePush");
objectActions["ObjectVariableRemoveAt"].SetFunctionName("variableRemoveAt");
objectConditions["ObjectVariableChildCount"].SetFunctionName(
"getVariableChildCount");
GetAllActions()["MoveObjects"].codeExtraInformation.SetCustomCodeGenerator(
// Instructions for the Resizable capability
objectActions["SetSize"].SetFunctionName("setSize");
objectConditions["Width"].SetFunctionName("getWidth");
objectActions["SetWidth"].SetFunctionName("setWidth");
objectConditions["Height"].SetFunctionName("getHeight");
objectActions["SetHeight"].SetFunctionName("setHeight");
// Instructions for the Scalable capability
objectExpressions["Scale"].SetFunctionName("getScale");
objectConditions["Scale"].SetFunctionName("getScale");
objectActions["SetScale"].SetFunctionName("setScale");
objectExpressions["ScaleX"].SetFunctionName("getScaleX");
objectConditions["ScaleX"].SetFunctionName("getScaleX");
objectActions["SetScaleX"].SetFunctionName("setScaleX");
objectExpressions["ScaleY"].SetFunctionName("getScaleY");
objectConditions["ScaleY"].SetFunctionName("getScaleY");
objectActions["SetScaleY"].SetFunctionName("setScaleY");
// Instructions for the Flippable capability
objectActions["FlipX"].SetFunctionName("flipX");
objectActions["FlipY"].SetFunctionName("flipY");
objectConditions["FlippedX"].SetFunctionName("isFlippedX");
objectConditions["FlippedY"].SetFunctionName("isFlippedY");
// Instructions for the Animable capability
objectExpressions["AnimationIndex"].SetFunctionName("getAnimationIndex");
objectConditions["AnimationIndex"].SetFunctionName("getAnimationIndex");
objectActions["SetAnimationIndex"].SetFunctionName("setAnimationIndex");
objectStrExpressions["AnimationName"].SetFunctionName("getAnimationName");
objectConditions["AnimationName"].SetFunctionName("isCurrentAnimationName");
objectActions["SetAnimationName"].SetFunctionName("setAnimationName");
objectActions["PauseAnimation"].SetFunctionName("pauseAnimation");
objectActions["PlayAnimation"].SetFunctionName("resumeAnimation");
objectExpressions["AnimationSpeedScale"].SetFunctionName(
"getAnimationSpeedScale");
objectConditions["AnimationSpeedScale"].SetFunctionName(
"getAnimationSpeedScale");
objectActions["SetAnimationSpeedScale"].SetFunctionName(
"setAnimationSpeedScale");
objectConditions["IsAnimationPaused"].SetFunctionName("isAnimationPaused");
objectConditions["HasAnimationEnded"].SetFunctionName("hasAnimationEnded");
GetAllActions()["MoveObjects"].SetCustomCodeGenerator(
[](gd::Instruction &,
gd::EventsCodeGenerator &,
gd::EventsCodeGenerationContext &) {
@@ -365,7 +312,7 @@ BaseObjectExtension::BaseObjectExtension() {
return op == "/" || op == "*" || op == "-" || op == "+";
};
objectActions["MettreXY"].codeExtraInformation.SetCustomCodeGenerator(
objectActions["MettreXY"].SetCustomCodeGenerator(
[&](gd::Instruction &instruction,
gd::EventsCodeGenerator &codeGenerator,
gd::EventsCodeGenerationContext &context) -> gd::String {
@@ -397,16 +344,16 @@ BaseObjectExtension::BaseObjectExtension() {
instruction.GetParameter(0).GetPlainString());
gd::String op1 = instruction.GetParameter(1).GetPlainString();
gd::String newX =
isNotAssignmentOperator(op1)
? (objectListName + "[i].getX() " + op1 + expression1Code)
: expression1Code;
gd::String newX = isNotAssignmentOperator(op1)
? (objectListName + "[i].getX() " + op1 + "(" +
expression1Code + ")")
: expression1Code;
gd::String op2 = instruction.GetParameter(3).GetPlainString();
gd::String newY =
isNotAssignmentOperator(op2)
? (objectListName + "[i].getY() " + op2 + expression2Code)
: expression2Code;
gd::String newY = isNotAssignmentOperator(op2)
? (objectListName + "[i].getY() " + op2 + "(" +
expression2Code + ")")
: expression2Code;
gd::String call =
objectListName + "[i].setPosition(" + newX + "," + newY + ")";
@@ -422,7 +369,7 @@ BaseObjectExtension::BaseObjectExtension() {
return outputCode;
});
objectActions["SetCenter"].codeExtraInformation.SetCustomCodeGenerator(
objectActions["SetCenter"].SetCustomCodeGenerator(
[&](gd::Instruction &instruction,
gd::EventsCodeGenerator &codeGenerator,
gd::EventsCodeGenerationContext &context) -> gd::String {
@@ -483,4 +430,4 @@ BaseObjectExtension::BaseObjectExtension() {
StripUnimplementedInstructionsAndExpressions();
}
} // namespace gdjs
} // namespace gdjs

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