mirror of
https://github.com/4ian/GDevelop.git
synced 2025-10-15 10:19:04 +00:00
Compare commits
90 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
656255a662 | ||
![]() |
ea7b7a778e | ||
![]() |
9b6de5affd | ||
![]() |
0c03659314 | ||
![]() |
6b08c0f033 | ||
![]() |
a1dcf03a5b | ||
![]() |
556d13c881 | ||
![]() |
0d6c42a9bf | ||
![]() |
690ce16ab4 | ||
![]() |
5f51a5e465 | ||
![]() |
b7521de138 | ||
![]() |
acea6fc595 | ||
![]() |
d8107fe3d5 | ||
![]() |
b40b95be99 | ||
![]() |
6644525dd0 | ||
![]() |
56e66d1c5a | ||
![]() |
90d8afb5a0 | ||
![]() |
d4db61a595 | ||
![]() |
90413b842d | ||
![]() |
43c788acbf | ||
![]() |
ee22b2e4b1 | ||
![]() |
007d56e946 | ||
![]() |
577c4adb14 | ||
![]() |
7f17720ff3 | ||
![]() |
288db1c941 | ||
![]() |
2496fc3eef | ||
![]() |
b43d5ec425 | ||
![]() |
3c43f28966 | ||
![]() |
a3f7c5782e | ||
![]() |
8dec6dfa28 | ||
![]() |
4eb49bdeb2 | ||
![]() |
813cadbd6e | ||
![]() |
58dd2c1a7b | ||
![]() |
104c27ebc8 | ||
![]() |
318099504c | ||
![]() |
8851be03a3 | ||
![]() |
a9a126ab0d | ||
![]() |
19e46fedc8 | ||
![]() |
ff987a0751 | ||
![]() |
0c0ab65b1a | ||
![]() |
52a5908d7e | ||
![]() |
49926a89a2 | ||
![]() |
b63b91f33d | ||
![]() |
67ea361416 | ||
![]() |
3b9078c6b3 | ||
![]() |
3d9e3f997e | ||
![]() |
3c34866faa | ||
![]() |
69cd2784c4 | ||
![]() |
5b7e419a41 | ||
![]() |
7773460d35 | ||
![]() |
9262266480 | ||
![]() |
84f2b4ca68 | ||
![]() |
19ae7a378c | ||
![]() |
f9ca330add | ||
![]() |
5ef990ac7d | ||
![]() |
8099820729 | ||
![]() |
df556f20e9 | ||
![]() |
2c8f2ab58d | ||
![]() |
20c3d62c90 | ||
![]() |
0a28981c74 | ||
![]() |
c8bb24475c | ||
![]() |
81bce61783 | ||
![]() |
71d1b6aa1f | ||
![]() |
c41974c24b | ||
![]() |
3bee88c6cd | ||
![]() |
4c874dfb7e | ||
![]() |
65f499f24e | ||
![]() |
3265bf7fb4 | ||
![]() |
5a437dea4e | ||
![]() |
19b576e8cc | ||
![]() |
67747e458e | ||
![]() |
260c2b9c8f | ||
![]() |
255ef1d8ef | ||
![]() |
53c633c646 | ||
![]() |
cec67a91d4 | ||
![]() |
4408dfe59d | ||
![]() |
c4274d2fc4 | ||
![]() |
b0103f31b7 | ||
![]() |
18905890d4 | ||
![]() |
6858e0fb59 | ||
![]() |
cf595a7d7d | ||
![]() |
e681d27bb8 | ||
![]() |
8941e04390 | ||
![]() |
e186681f39 | ||
![]() |
a578fa32e9 | ||
![]() |
6b40e8309c | ||
![]() |
5ff51351af | ||
![]() |
d66e4e0001 | ||
![]() |
2184eaf70b | ||
![]() |
29fc0598f6 |
@@ -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)
|
||||
|
123
CMakeLists.txt
123
CMakeLists.txt
@@ -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()
|
||||
|
@@ -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()
|
||||
|
@@ -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);
|
||||
@@ -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);
|
||||
}
|
||||
@@ -1019,15 +1019,15 @@ gd::String EventsCodeGenerator::GenerateFreeCondition(
|
||||
bool conditionInverted,
|
||||
gd::EventsCodeGenerationContext& context) {
|
||||
// Generate call
|
||||
gd::String predicat;
|
||||
gd::String predicate;
|
||||
if (instrInfos.codeExtraInformation.type == "number" ||
|
||||
instrInfos.codeExtraInformation.type == "string") {
|
||||
predicat = GenerateRelationalOperatorCall(
|
||||
predicate = GenerateRelationalOperatorCall(
|
||||
instrInfos,
|
||||
arguments,
|
||||
instrInfos.codeExtraInformation.functionCallName);
|
||||
} else {
|
||||
predicat = instrInfos.codeExtraInformation.functionCallName + "(" +
|
||||
predicate = instrInfos.codeExtraInformation.functionCallName + "(" +
|
||||
GenerateArgumentsList(arguments, 0) + ")";
|
||||
}
|
||||
|
||||
@@ -1040,10 +1040,10 @@ gd::String EventsCodeGenerator::GenerateFreeCondition(
|
||||
conditionAlreadyTakeCareOfInversion = true;
|
||||
}
|
||||
if (!conditionAlreadyTakeCareOfInversion && conditionInverted)
|
||||
predicat = GenerateNegatedPredicat(predicat);
|
||||
predicate = GenerateNegatedPredicate(predicate);
|
||||
|
||||
// Generate condition code
|
||||
return returnBoolean + " = " + predicat + ";\n";
|
||||
return returnBoolean + " = " + predicate + ";\n";
|
||||
}
|
||||
|
||||
gd::String EventsCodeGenerator::GenerateObjectCondition(
|
||||
@@ -1065,18 +1065,18 @@ gd::String EventsCodeGenerator::GenerateObjectCondition(
|
||||
instrInfos.codeExtraInformation.functionCallName;
|
||||
|
||||
// Create call
|
||||
gd::String predicat;
|
||||
gd::String predicate;
|
||||
if ((instrInfos.codeExtraInformation.type == "number" ||
|
||||
instrInfos.codeExtraInformation.type == "string")) {
|
||||
predicat = GenerateRelationalOperatorCall(
|
||||
predicate = GenerateRelationalOperatorCall(
|
||||
instrInfos, arguments, objectFunctionCallNamePart, 1);
|
||||
} else {
|
||||
predicat = objectFunctionCallNamePart + "(" +
|
||||
predicate = objectFunctionCallNamePart + "(" +
|
||||
GenerateArgumentsList(arguments, 1) + ")";
|
||||
}
|
||||
if (conditionInverted) predicat = GenerateNegatedPredicat(predicat);
|
||||
if (conditionInverted) predicate = GenerateNegatedPredicate(predicate);
|
||||
|
||||
return "For each picked object \"" + objectName + "\", check " + predicat +
|
||||
return "For each picked object \"" + objectName + "\", check " + predicate +
|
||||
".\n";
|
||||
}
|
||||
|
||||
@@ -1090,16 +1090,16 @@ gd::String EventsCodeGenerator::GenerateBehaviorCondition(
|
||||
bool conditionInverted,
|
||||
gd::EventsCodeGenerationContext& context) {
|
||||
// Create call
|
||||
gd::String predicat;
|
||||
gd::String predicate;
|
||||
if ((instrInfos.codeExtraInformation.type == "number" ||
|
||||
instrInfos.codeExtraInformation.type == "string")) {
|
||||
predicat = GenerateRelationalOperatorCall(instrInfos, arguments, "", 2);
|
||||
predicate = GenerateRelationalOperatorCall(instrInfos, arguments, "", 2);
|
||||
} else {
|
||||
predicat = "(" + GenerateArgumentsList(arguments, 2) + ")";
|
||||
predicate = "(" + GenerateArgumentsList(arguments, 2) + ")";
|
||||
}
|
||||
if (conditionInverted) predicat = GenerateNegatedPredicat(predicat);
|
||||
if (conditionInverted) predicate = GenerateNegatedPredicate(predicate);
|
||||
|
||||
return "For each picked object \"" + objectName + "\", check " + predicat +
|
||||
return "For each picked object \"" + objectName + "\", check " + predicate +
|
||||
" for behavior \"" + behaviorName + "\".\n";
|
||||
}
|
||||
|
||||
|
@@ -668,13 +668,13 @@ class GD_CORE_API EventsCodeGenerator {
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Must negate a predicat.
|
||||
* \brief Must negate a predicate.
|
||||
*
|
||||
* The default implementation generates C-style code : It wraps the predicat
|
||||
* The default implementation generates C-style code : It wraps the predicate
|
||||
* inside parenthesis and add a !.
|
||||
*/
|
||||
virtual gd::String GenerateNegatedPredicat(const gd::String& predicat) const {
|
||||
return "!(" + predicat + ")";
|
||||
virtual gd::String GenerateNegatedPredicate(const gd::String& predicate) const {
|
||||
return "!(" + predicate + ")";
|
||||
};
|
||||
|
||||
virtual gd::String GenerateFreeCondition(
|
||||
|
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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>
|
||||
|
@@ -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");
|
||||
|
@@ -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(){};
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -287,7 +287,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
|
||||
|
||||
obj.AddCondition("AnimationName",
|
||||
_("Current animation name"),
|
||||
_("Check the animation by played by the object."),
|
||||
_("Check the animation played by the object."),
|
||||
_("The animation of _PARAM0_ is _PARAM1_"),
|
||||
_("Animations and images"),
|
||||
"res/conditions/animation24.png",
|
||||
|
@@ -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");
|
||||
|
@@ -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
|
||||
|
@@ -172,7 +172,7 @@ BuiltinExtensionsImplementer::ImplementsStringInstructionsExtension(
|
||||
_("Search the last occurrence in a text, starting from a position"),
|
||||
_("Search in a text the last occurrence, starting from a position "
|
||||
"(return "
|
||||
" the position of the result, from the beginning of the string, or "
|
||||
"the position of the result, from the beginning of the string, or "
|
||||
"-1 if not found)"),
|
||||
"",
|
||||
"res/conditions/toujours24_black.png")
|
||||
|
135
Core/GDCore/Extensions/Metadata/AbstractFunctionMetadata.h
Normal file
135
Core/GDCore/Extensions/Metadata/AbstractFunctionMetadata.h
Normal file
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* 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"
|
||||
#include "ParameterMetadata.h"
|
||||
#include "ParameterOptions.h"
|
||||
|
||||
namespace gd {
|
||||
class Project;
|
||||
class Layout;
|
||||
class EventsCodeGenerator;
|
||||
class EventsCodeGenerationContext;
|
||||
class SerializerElement;
|
||||
} // 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 &defaultValue) = 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
|
@@ -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 BEHAVIORMETADATA_H
|
||||
#define BEHAVIORMETADATA_H
|
||||
#pragma once
|
||||
|
||||
#include "InstructionOrExpressionContainerMetadata.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "GDCore/Extensions/Metadata/ExpressionMetadata.h"
|
||||
@@ -25,7 +27,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 +69,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 +82,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 +93,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 +104,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 +112,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 +121,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 +136,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 +153,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 +162,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 +172,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 +195,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 +205,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 +223,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,17 +232,17 @@ 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.
|
||||
@@ -293,22 +295,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;
|
||||
@@ -337,5 +339,3 @@ class GD_CORE_API BehaviorMetadata {
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
||||
#endif // BEHAVIORMETADATA_H
|
||||
|
@@ -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,7 +218,8 @@ 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;
|
||||
}
|
||||
@@ -312,50 +241,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 +260,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 +369,3 @@ class GD_CORE_API ExpressionMetadata {
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
||||
#endif
|
||||
#endif // EXPRESSIONMETADATA_H
|
||||
|
@@ -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>
|
||||
@@ -33,7 +35,7 @@ namespace gd {
|
||||
*
|
||||
* \ingroup Events
|
||||
*/
|
||||
class GD_CORE_API InstructionMetadata {
|
||||
class GD_CORE_API InstructionMetadata : public gd::AbstractFunctionMetadata {
|
||||
public:
|
||||
/**
|
||||
* Construct a new instruction metadata.
|
||||
@@ -96,7 +98,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 +135,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 +143,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 +151,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 +159,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 +194,7 @@ class GD_CORE_API InstructionMetadata {
|
||||
*
|
||||
* Used mainly when an instruction is deprecated.
|
||||
*/
|
||||
InstructionMetadata &SetHidden() {
|
||||
InstructionMetadata &SetHidden() override {
|
||||
hidden = true;
|
||||
return *this;
|
||||
}
|
||||
@@ -231,7 +233,7 @@ class GD_CORE_API InstructionMetadata {
|
||||
const gd::String &type,
|
||||
const gd::String &label,
|
||||
const gd::String &supplementaryInformation = "",
|
||||
bool parameterIsOptional = false);
|
||||
bool parameterIsOptional = false) override;
|
||||
|
||||
/**
|
||||
* \brief Add a parameter not displayed in editor.
|
||||
@@ -245,7 +247,7 @@ class GD_CORE_API InstructionMetadata {
|
||||
* \see EventsCodeGenerator::GenerateParametersCodes
|
||||
*/
|
||||
InstructionMetadata &AddCodeOnlyParameter(
|
||||
const gd::String &type, const gd::String &supplementaryInformation);
|
||||
const gd::String &type, const gd::String &supplementaryInformation) override;
|
||||
|
||||
/**
|
||||
* \brief Set the default value used in editor (or if an optional parameter is
|
||||
@@ -253,7 +255,7 @@ class GD_CORE_API InstructionMetadata {
|
||||
*
|
||||
* \see AddParameter
|
||||
*/
|
||||
InstructionMetadata &SetDefaultValue(const gd::String &defaultValue_) {
|
||||
InstructionMetadata &SetDefaultValue(const gd::String &defaultValue_) override {
|
||||
if (!parameters.empty()) parameters.back().SetDefaultValue(defaultValue_);
|
||||
return *this;
|
||||
};
|
||||
@@ -265,7 +267,7 @@ class GD_CORE_API InstructionMetadata {
|
||||
* \see AddParameter
|
||||
*/
|
||||
InstructionMetadata &SetParameterLongDescription(
|
||||
const gd::String &longDescription) {
|
||||
const gd::String &longDescription) override {
|
||||
if (!parameters.empty())
|
||||
parameters.back().SetLongDescription(longDescription);
|
||||
return *this;
|
||||
@@ -278,7 +280,7 @@ class GD_CORE_API InstructionMetadata {
|
||||
*
|
||||
* \see AddParameter
|
||||
*/
|
||||
InstructionMetadata &SetParameterExtraInfo(const gd::String &extraInfo) {
|
||||
InstructionMetadata &SetParameterExtraInfo(const gd::String &extraInfo) override {
|
||||
if (!parameters.empty()) parameters.back().SetExtraInfo(extraInfo);
|
||||
return *this;
|
||||
}
|
||||
@@ -382,128 +384,13 @@ class GD_CORE_API InstructionMetadata {
|
||||
/**
|
||||
* \brief Defines information about how generate the code for an instruction
|
||||
*/
|
||||
class ExtraInformation {
|
||||
class ExtraInformation {
|
||||
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;
|
||||
@@ -512,75 +399,156 @@ class GD_CORE_API InstructionMetadata {
|
||||
std::map<gd::String, gd::String> optionalMutators;
|
||||
bool hasCustomCodeGenerator;
|
||||
std::function<gd::String(Instruction &instruction,
|
||||
gd::EventsCodeGenerator &codeGenerator,
|
||||
gd::EventsCodeGenerationContext &context)>
|
||||
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_);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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:
|
||||
@@ -604,5 +572,3 @@ class GD_CORE_API InstructionMetadata {
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
||||
#endif // INSTRUCTIONMETADATA_H
|
||||
|
@@ -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
|
@@ -135,11 +135,11 @@ MetadataProvider::GetExtensionAndConditionMetadata(const gd::Platform& platform,
|
||||
|
||||
const auto& objects = extension->GetExtensionObjectsTypes();
|
||||
for (const gd::String& extObjectType : objects) {
|
||||
const auto& allObjetsConditions =
|
||||
const auto& allObjectsConditions =
|
||||
extension->GetAllConditionsForObject(extObjectType);
|
||||
if (allObjetsConditions.find(conditionType) != allObjetsConditions.end())
|
||||
if (allObjectsConditions.find(conditionType) != allObjectsConditions.end())
|
||||
return ExtensionAndMetadata<InstructionMetadata>(
|
||||
*extension, allObjetsConditions.find(conditionType)->second);
|
||||
*extension, allObjectsConditions.find(conditionType)->second);
|
||||
}
|
||||
|
||||
const auto& autos = extension->GetBehaviorsTypes();
|
||||
|
@@ -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
|
@@ -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,7 +85,7 @@ class GD_CORE_API MultipleInstructionMetadata {
|
||||
* \see gd::InstructionMetadata::SetParameterExtraInfo
|
||||
*/
|
||||
MultipleInstructionMetadata &SetParameterExtraInfo(
|
||||
const gd::String &defaultValue) {
|
||||
const gd::String &defaultValue) override {
|
||||
if (expression) expression->SetParameterExtraInfo(defaultValue);
|
||||
if (condition) condition->SetParameterExtraInfo(defaultValue);
|
||||
if (action) action->SetParameterExtraInfo(defaultValue);
|
||||
@@ -96,7 +96,7 @@ class GD_CORE_API MultipleInstructionMetadata {
|
||||
* \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 +106,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();
|
||||
@@ -136,47 +136,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 +184,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 +218,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 +278,3 @@ class GD_CORE_API MultipleInstructionMetadata {
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
||||
#endif // MULTIPLEINSTRUCTIONSMETADATA_H
|
||||
|
@@ -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;
|
||||
}
|
||||
@@ -248,12 +250,12 @@ class GD_CORE_API ObjectMetadata {
|
||||
return unsupportedBaseObjectCapabilities.find(capability) != unsupportedBaseObjectCapabilities.end();
|
||||
}
|
||||
|
||||
const gd::String& GetName() const { return name; }
|
||||
const gd::String& GetFullName() const { return fullname; }
|
||||
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 +269,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.
|
||||
@@ -341,4 +343,3 @@ class GD_CORE_API ObjectMetadata {
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
#endif // OBJECTMETADATA_H
|
||||
|
@@ -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;
|
||||
|
@@ -642,7 +642,7 @@ std::vector<EventsSearchResult> EventsRefactorer::ReplaceStringInEvents(
|
||||
return modifiedEvents;
|
||||
}
|
||||
|
||||
gd::String ReplaceAllOccurencesCaseUnsensitive(gd::String context,
|
||||
gd::String ReplaceAllOccurrencesCaseInsensitive(gd::String context,
|
||||
gd::String from,
|
||||
const gd::String& to) {
|
||||
size_t lookHere = 0;
|
||||
@@ -673,7 +673,7 @@ bool EventsRefactorer::ReplaceStringInActions(gd::ObjectsContainer& project,
|
||||
matchCase
|
||||
? actions[aId].GetParameter(pNb).GetPlainString().FindAndReplace(
|
||||
toReplace, newString, true)
|
||||
: ReplaceAllOccurencesCaseUnsensitive(
|
||||
: ReplaceAllOccurrencesCaseInsensitive(
|
||||
actions[aId].GetParameter(pNb).GetPlainString(),
|
||||
toReplace,
|
||||
newString);
|
||||
@@ -713,7 +713,7 @@ bool EventsRefactorer::ReplaceStringInConditions(
|
||||
.GetParameter(pNb)
|
||||
.GetPlainString()
|
||||
.FindAndReplace(toReplace, newString, true)
|
||||
: ReplaceAllOccurencesCaseUnsensitive(
|
||||
: ReplaceAllOccurrencesCaseInsensitive(
|
||||
conditions[cId].GetParameter(pNb).GetPlainString(),
|
||||
toReplace,
|
||||
newString);
|
||||
@@ -749,7 +749,7 @@ bool EventsRefactorer::ReplaceStringInEventSearchableStrings(
|
||||
for (std::size_t sNb = 0; sNb < stringEvent.size(); ++sNb) {
|
||||
gd::String newStringEvent =
|
||||
matchCase ? stringEvent[sNb].FindAndReplace(toReplace, newString, true)
|
||||
: ReplaceAllOccurencesCaseUnsensitive(
|
||||
: ReplaceAllOccurrencesCaseInsensitive(
|
||||
stringEvent[sNb], toReplace, newString);
|
||||
newEventStrings.push_back(newStringEvent);
|
||||
}
|
||||
|
@@ -153,6 +153,8 @@ void CustomObjectConfiguration::ExposeResources(gd::ArbitraryResourceWorker& wor
|
||||
worker.ExposeTileset(newPropertyValue);
|
||||
} else if (resourceType == "bitmapFont") {
|
||||
worker.ExposeBitmapFont(newPropertyValue);
|
||||
} else if (resourceType == "model3D") {
|
||||
worker.ExposeModel3D(newPropertyValue);
|
||||
}
|
||||
|
||||
if (newPropertyValue != oldPropertyValue) {
|
||||
|
@@ -77,7 +77,7 @@ class GD_CORE_API EventsBasedBehavior: public AbstractEventsBasedEntity {
|
||||
* \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
|
||||
|
@@ -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.
|
||||
|
@@ -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
|
||||
|
@@ -9,9 +9,9 @@
|
||||
#include "GDCore/Project/Layout.h"
|
||||
#include "GDCore/Project/Object.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/Project/PropertyDescriptor.h"
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
#include "GDCore/Tools/UUID/UUID.h"
|
||||
#include "GDCore/Project/PropertyDescriptor.h"
|
||||
|
||||
namespace gd {
|
||||
|
||||
@@ -21,12 +21,17 @@ InitialInstance::InitialInstance()
|
||||
: objectName(""),
|
||||
x(0),
|
||||
y(0),
|
||||
z(0),
|
||||
angle(0),
|
||||
rotationX(0),
|
||||
rotationY(0),
|
||||
zOrder(0),
|
||||
layer(""),
|
||||
personalizedSize(false),
|
||||
customSize(false),
|
||||
customDepth(false),
|
||||
width(0),
|
||||
height(0),
|
||||
depth(0),
|
||||
locked(false),
|
||||
sealed(false),
|
||||
persistentUuid(UUID::MakeUuid4()) {}
|
||||
@@ -35,11 +40,20 @@ void InitialInstance::UnserializeFrom(const SerializerElement& element) {
|
||||
SetObjectName(element.GetStringAttribute("name", "", "nom"));
|
||||
SetX(element.GetDoubleAttribute("x"));
|
||||
SetY(element.GetDoubleAttribute("y"));
|
||||
SetZ(element.GetDoubleAttribute("z", 0));
|
||||
SetAngle(element.GetDoubleAttribute("angle"));
|
||||
SetRotationX(element.GetDoubleAttribute("rotationX", 0));
|
||||
SetRotationY(element.GetDoubleAttribute("rotationY", 0));
|
||||
SetHasCustomSize(
|
||||
element.GetBoolAttribute("customSize", false, "personalizedSize"));
|
||||
SetCustomWidth(element.GetDoubleAttribute("width"));
|
||||
SetCustomHeight(element.GetDoubleAttribute("height"));
|
||||
if (element.HasChild("depth") || element.HasAttribute("depth")) {
|
||||
SetHasCustomDepth(true);
|
||||
SetCustomDepth(element.GetDoubleAttribute("depth"));
|
||||
} else {
|
||||
SetHasCustomDepth(false);
|
||||
}
|
||||
SetZOrder(element.GetIntAttribute("zOrder", 0, "plan"));
|
||||
SetLayer(element.GetStringAttribute("layer"));
|
||||
SetLocked(element.GetBoolAttribute("locked", false));
|
||||
@@ -53,9 +67,26 @@ void InitialInstance::UnserializeFrom(const SerializerElement& element) {
|
||||
element.GetChild("numberProperties", 0, "floatInfos");
|
||||
numberPropertiesElement.ConsiderAsArrayOf("property", "Info");
|
||||
for (std::size_t j = 0; j < numberPropertiesElement.GetChildrenCount(); ++j) {
|
||||
gd::String name = numberPropertiesElement.GetChild(j).GetStringAttribute("name");
|
||||
double value = numberPropertiesElement.GetChild(j).GetDoubleAttribute("value");
|
||||
numberProperties[name] = value;
|
||||
gd::String name =
|
||||
numberPropertiesElement.GetChild(j).GetStringAttribute("name");
|
||||
double value =
|
||||
numberPropertiesElement.GetChild(j).GetDoubleAttribute("value");
|
||||
|
||||
// Compatibility with GD <= 5.1.164
|
||||
if (name == "z") {
|
||||
SetZ(value);
|
||||
} else if (name == "rotationX") {
|
||||
SetRotationX(value);
|
||||
} else if (name == "rotationY") {
|
||||
SetRotationY(value);
|
||||
} else if (name == "depth") {
|
||||
SetHasCustomDepth(true);
|
||||
SetCustomDepth(value);
|
||||
}
|
||||
// end of compatibility code
|
||||
else {
|
||||
numberProperties[name] = value;
|
||||
}
|
||||
}
|
||||
|
||||
stringProperties.clear();
|
||||
@@ -77,21 +108,26 @@ void InitialInstance::SerializeTo(SerializerElement& element) const {
|
||||
element.SetAttribute("name", GetObjectName());
|
||||
element.SetAttribute("x", GetX());
|
||||
element.SetAttribute("y", GetY());
|
||||
if (GetZ() != 0) element.SetAttribute("z", GetZ());
|
||||
element.SetAttribute("zOrder", GetZOrder());
|
||||
element.SetAttribute("layer", GetLayer());
|
||||
element.SetAttribute("angle", GetAngle());
|
||||
if (GetRotationX() != 0) element.SetAttribute("rotationX", GetRotationX());
|
||||
if (GetRotationY() != 0) element.SetAttribute("rotationY", GetRotationY());
|
||||
element.SetAttribute("customSize", HasCustomSize());
|
||||
element.SetAttribute("width", GetCustomWidth());
|
||||
element.SetAttribute("height", GetCustomHeight());
|
||||
if (HasCustomDepth()) element.SetAttribute("depth", GetCustomDepth());
|
||||
if (IsLocked()) element.SetAttribute("locked", IsLocked());
|
||||
if (IsSealed()) element.SetAttribute("sealed", IsSealed());
|
||||
|
||||
if (persistentUuid.empty()) persistentUuid = UUID::MakeUuid4();
|
||||
element.SetStringAttribute("persistentUuid", persistentUuid);
|
||||
|
||||
SerializerElement& numberPropertiesElement = element.AddChild("numberProperties");
|
||||
SerializerElement& numberPropertiesElement =
|
||||
element.AddChild("numberProperties");
|
||||
numberPropertiesElement.ConsiderAsArrayOf("property");
|
||||
for (const auto& property: numberProperties) {
|
||||
for (const auto& property : numberProperties) {
|
||||
numberPropertiesElement.AddChild("property")
|
||||
.SetAttribute("name", property.first)
|
||||
.SetAttribute("value", property.second);
|
||||
@@ -99,7 +135,7 @@ void InitialInstance::SerializeTo(SerializerElement& element) const {
|
||||
|
||||
SerializerElement& stringPropElement = element.AddChild("stringProperties");
|
||||
stringPropElement.ConsiderAsArrayOf("property");
|
||||
for (const auto& property: stringProperties) {
|
||||
for (const auto& property : stringProperties) {
|
||||
stringPropElement.AddChild("property")
|
||||
.SetAttribute("name", property.first)
|
||||
.SetAttribute("value", property.second);
|
||||
@@ -117,10 +153,12 @@ std::map<gd::String, gd::PropertyDescriptor>
|
||||
InitialInstance::GetCustomProperties(gd::Project& project, gd::Layout& layout) {
|
||||
// Find an object
|
||||
if (layout.HasObjectNamed(GetObjectName()))
|
||||
return layout.GetObject(GetObjectName()).GetConfiguration()
|
||||
return layout.GetObject(GetObjectName())
|
||||
.GetConfiguration()
|
||||
.GetInitialInstanceProperties(*this, project, layout);
|
||||
else if (project.HasObjectNamed(GetObjectName()))
|
||||
return project.GetObject(GetObjectName()).GetConfiguration()
|
||||
return project.GetObject(GetObjectName())
|
||||
.GetConfiguration()
|
||||
.GetInitialInstanceProperties(*this, project, layout);
|
||||
|
||||
std::map<gd::String, gd::PropertyDescriptor> nothing;
|
||||
@@ -132,10 +170,12 @@ bool InitialInstance::UpdateCustomProperty(const gd::String& name,
|
||||
gd::Project& project,
|
||||
gd::Layout& layout) {
|
||||
if (layout.HasObjectNamed(GetObjectName()))
|
||||
return layout.GetObject(GetObjectName()).GetConfiguration()
|
||||
return layout.GetObject(GetObjectName())
|
||||
.GetConfiguration()
|
||||
.UpdateInitialInstanceProperty(*this, name, value, project, layout);
|
||||
else if (project.HasObjectNamed(GetObjectName()))
|
||||
return project.GetObject(GetObjectName()).GetConfiguration()
|
||||
return project.GetObject(GetObjectName())
|
||||
.GetConfiguration()
|
||||
.UpdateInitialInstanceProperty(*this, name, value, project, layout);
|
||||
|
||||
return false;
|
||||
@@ -154,7 +194,8 @@ const gd::String& InitialInstance::GetRawStringProperty(
|
||||
return it != stringProperties.end() ? it->second : *badStringProperyValue;
|
||||
}
|
||||
|
||||
void InitialInstance::SetRawDoubleProperty(const gd::String& name, double value) {
|
||||
void InitialInstance::SetRawDoubleProperty(const gd::String& name,
|
||||
double value) {
|
||||
numberProperties[name] = value;
|
||||
}
|
||||
|
||||
|
@@ -73,22 +73,52 @@ class GD_CORE_API InitialInstance {
|
||||
void SetY(double y_) { y = y_; }
|
||||
|
||||
/**
|
||||
* \brief Get the rotation of the instance, in radians.
|
||||
* \brief Get the Z position of the instance
|
||||
*/
|
||||
double GetZ() const { return z; }
|
||||
|
||||
/**
|
||||
* \brief Set the Z position of the instance
|
||||
*/
|
||||
void SetZ(double z_) { z = z_; }
|
||||
|
||||
/**
|
||||
* \brief Get the rotation of the instance on Z axis, in radians.
|
||||
*/
|
||||
double GetAngle() const { return angle; }
|
||||
|
||||
/**
|
||||
* \brief Set the rotation of the instance, in radians.
|
||||
* \brief Set the rotation of the instance on Z axis, in radians.
|
||||
*/
|
||||
void SetAngle(double angle_) { angle = angle_; }
|
||||
|
||||
/**
|
||||
* \brief Get the Z order of the instance.
|
||||
* \brief Get the rotation of the instance on X axis, in radians.
|
||||
*/
|
||||
double GetRotationX() const { return rotationX; }
|
||||
|
||||
/**
|
||||
* \brief Set the rotation of the instance on X axis, in radians.
|
||||
*/
|
||||
void SetRotationX(double rotationX_) { rotationX = rotationX_; }
|
||||
|
||||
/**
|
||||
* \brief Get the rotation of the instance on Y axis, in radians.
|
||||
*/
|
||||
double GetRotationY() const { return rotationY; }
|
||||
|
||||
/**
|
||||
* \brief Set the rotation of the instance on Y axis, in radians.
|
||||
*/
|
||||
void SetRotationY(double rotationY_) { rotationY = rotationY_; }
|
||||
|
||||
/**
|
||||
* \brief Get the Z order of the instance (for a 2D object).
|
||||
*/
|
||||
int GetZOrder() const { return zOrder; }
|
||||
|
||||
/**
|
||||
* \brief Set the Z order of the instance.
|
||||
* \brief Set the Z order of the instance (for a 2D object).
|
||||
*/
|
||||
void SetZOrder(int zOrder_) { zOrder = zOrder_; }
|
||||
|
||||
@@ -103,29 +133,51 @@ class GD_CORE_API InitialInstance {
|
||||
void SetLayer(const gd::String& layer_) { layer = layer_; }
|
||||
|
||||
/**
|
||||
* \brief Return true if the instance has a size which is different from its
|
||||
* object default size.
|
||||
* \brief Return true if the instance has a width/height which is different from its
|
||||
* object default width/height. This is independent from `HasCustomDepth`.
|
||||
*
|
||||
* \see gd::Object
|
||||
*/
|
||||
bool HasCustomSize() const { return personalizedSize; }
|
||||
bool HasCustomSize() const { return customSize; }
|
||||
|
||||
/**
|
||||
* \brief Set whether the instance has a size which is different from its
|
||||
* object default size or not.
|
||||
* \brief Return true if the instance has a depth which is different from its
|
||||
* object default depth. This is independent from `HasCustomSize`.
|
||||
*
|
||||
* \param hasCustomSize true if the size is different from the object's
|
||||
* default size. \see gd::Object
|
||||
* \see gd::Object
|
||||
*/
|
||||
bool HasCustomDepth() const { return customDepth; }
|
||||
|
||||
/**
|
||||
* \brief Set whether the instance has a width/height which is different from its
|
||||
* object default width/height or not.
|
||||
* This is independent from `SetHasCustomDepth`.
|
||||
*
|
||||
* \see gd::Object
|
||||
*/
|
||||
void SetHasCustomSize(bool hasCustomSize_) {
|
||||
personalizedSize = hasCustomSize_;
|
||||
customSize = hasCustomSize_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set whether the instance has a depth which is different from its
|
||||
* object default depth or not.
|
||||
* This is independent from `SetHasCustomSize`.
|
||||
*
|
||||
* \param hasCustomSize true if the depth is different from the object's
|
||||
* default depth.
|
||||
* \see gd::Object
|
||||
*/
|
||||
void SetHasCustomDepth(bool hasCustomDepth_) {
|
||||
customDepth = hasCustomDepth_;
|
||||
}
|
||||
|
||||
double GetCustomWidth() const { return width; }
|
||||
void SetCustomWidth(double width_) { width = width_; }
|
||||
|
||||
double GetCustomHeight() const { return height; }
|
||||
void SetCustomHeight(double height_) { height = height_; }
|
||||
double GetCustomDepth() const { return depth; }
|
||||
void SetCustomDepth(double depth_) { depth = depth_; }
|
||||
|
||||
/**
|
||||
* \brief Return true if the instance is locked and cannot be moved in the
|
||||
@@ -272,14 +324,19 @@ class GD_CORE_API InitialInstance {
|
||||
stringProperties; ///< More data which can be used by the object
|
||||
|
||||
gd::String objectName; ///< Object name
|
||||
double x; ///< Object initial X position
|
||||
double y; ///< Object initial Y position
|
||||
double angle; ///< Object initial angle
|
||||
int zOrder; ///< Object initial Z order
|
||||
gd::String layer; ///< Object initial layer
|
||||
bool personalizedSize; ///< True if object has a custom size
|
||||
double width; ///< Object custom width
|
||||
double height; ///< Object custom height
|
||||
double x; ///< Instance X position
|
||||
double y; ///< Instance Y position
|
||||
double z; ///< Instance Z position (for a 3D object)
|
||||
double angle; ///< Instance angle on Z axis
|
||||
double rotationX; ///< Instance angle on X axis (for a 3D object)
|
||||
double rotationY; ///< Instance angle on Y axis (for a 3D object)
|
||||
int zOrder; ///< Instance Z order (for a 2D object)
|
||||
gd::String layer; ///< Instance layer
|
||||
bool customSize; ///< True if object has a custom width and height
|
||||
bool customDepth; ///< True if object has a custom depth
|
||||
double width; ///< Instance custom width
|
||||
double height; ///< Instance custom height
|
||||
double depth; ///< Instance custom depth
|
||||
gd::VariablesContainer initialVariables; ///< Instance specific variables
|
||||
bool locked; ///< True if the instance is locked
|
||||
bool sealed; ///< True if the instance is sealed
|
||||
|
@@ -68,14 +68,14 @@ gd::InitialInstance& InitialInstancesContainer::InsertNewInitialInstance() {
|
||||
}
|
||||
|
||||
void InitialInstancesContainer::RemoveInstanceIf(
|
||||
std::function<bool(const gd::InitialInstance&)> predicat) {
|
||||
std::function<bool(const gd::InitialInstance&)> predicate) {
|
||||
// Note that we can't use erase–remove idiom here because remove_if would
|
||||
// move the instances, and the container must guarantee that
|
||||
// iterators/pointers to instances always remain valid.
|
||||
for (std::list<gd::InitialInstance>::iterator it = initialInstances.begin(),
|
||||
end = initialInstances.end();
|
||||
it != end;) {
|
||||
if (predicat(*it))
|
||||
if (predicate(*it))
|
||||
it = initialInstances.erase(it);
|
||||
else
|
||||
++it;
|
||||
|
@@ -178,7 +178,7 @@ class GD_CORE_API InitialInstancesContainer {
|
||||
|
||||
private:
|
||||
void RemoveInstanceIf(
|
||||
std::function<bool(const gd::InitialInstance &)> predicat);
|
||||
std::function<bool(const gd::InitialInstance &)> predicate);
|
||||
|
||||
std::list<gd::InitialInstance> initialInstances;
|
||||
|
||||
|
@@ -127,6 +127,10 @@ class GD_CORE_API Object {
|
||||
/** \brief Return the tags of the object.
|
||||
*/
|
||||
const gd::String& GetTags() const { return tags; }
|
||||
|
||||
/** \brief Shortcut to check if the object is a 3D object.
|
||||
*/
|
||||
bool Is3DObject() const { return configuration->Is3DObject(); }
|
||||
///@}
|
||||
|
||||
/** \name Behaviors management
|
||||
|
@@ -20,7 +20,7 @@ namespace gd {
|
||||
|
||||
ObjectConfiguration::~ObjectConfiguration() {}
|
||||
|
||||
ObjectConfiguration::ObjectConfiguration() {}
|
||||
ObjectConfiguration::ObjectConfiguration(): is3DObject(false) {}
|
||||
|
||||
std::map<gd::String, gd::PropertyDescriptor> ObjectConfiguration::GetProperties() const {
|
||||
std::map<gd::String, gd::PropertyDescriptor> nothing;
|
||||
|
@@ -61,12 +61,22 @@ class GD_CORE_API ObjectConfiguration {
|
||||
|
||||
/** \brief Change the type of the object.
|
||||
*/
|
||||
void SetType(const gd::String& type_) { type = type_; }
|
||||
void SetType(const gd::String& type_) {
|
||||
type = type_;
|
||||
|
||||
// For now, as a shortcut, consider only the objects from the built-in 3D extension
|
||||
// to be 3D object.
|
||||
is3DObject = type.find("Scene3D::") == 0;
|
||||
}
|
||||
|
||||
/** \brief Return the type of the object.
|
||||
*/
|
||||
const gd::String& GetType() const { return type; }
|
||||
|
||||
/** \brief Shortcut to check if the object is a 3D object.
|
||||
*/
|
||||
bool Is3DObject() const { return is3DObject; }
|
||||
|
||||
/** \name Object properties
|
||||
* Reading and updating object configuration properties
|
||||
*/
|
||||
@@ -170,6 +180,7 @@ class GD_CORE_API ObjectConfiguration {
|
||||
protected:
|
||||
gd::String type; ///< Which type of object is represented by this
|
||||
///< configuration.
|
||||
bool is3DObject;
|
||||
|
||||
/**
|
||||
* \brief Derived object configuration can redefine this method to load
|
||||
|
@@ -65,6 +65,8 @@ Project::Project()
|
||||
pixelsRounding(false),
|
||||
adaptGameResolutionAtRuntime(true),
|
||||
sizeOnStartupMode("adaptWidth"),
|
||||
antialiasingMode("MSAA"),
|
||||
isAntialisingEnabledOnMobile(false),
|
||||
projectUuid(""),
|
||||
useDeprecatedZeroAsDefaultZOrder(false),
|
||||
useExternalSourceFiles(false),
|
||||
@@ -628,6 +630,8 @@ void Project::UnserializeFrom(const SerializerElement& element) {
|
||||
SetAdaptGameResolutionAtRuntime(
|
||||
propElement.GetBoolAttribute("adaptGameResolutionAtRuntime", false));
|
||||
SetSizeOnStartupMode(propElement.GetStringAttribute("sizeOnStartupMode", ""));
|
||||
SetAntialiasingMode(propElement.GetStringAttribute("antialiasingMode", "MSAA"));
|
||||
SetAntialisingEnabledOnMobile(propElement.GetBoolAttribute("antialisingEnabledOnMobile", false));
|
||||
SetProjectUuid(propElement.GetStringAttribute("projectUuid", ""));
|
||||
SetAuthor(propElement.GetChild("author", 0, "Auteur").GetValue().GetString());
|
||||
SetPackageName(propElement.GetStringAttribute("packageName"));
|
||||
@@ -882,6 +886,8 @@ void Project::SerializeTo(SerializerElement& element) const {
|
||||
propElement.SetAttribute("adaptGameResolutionAtRuntime",
|
||||
adaptGameResolutionAtRuntime);
|
||||
propElement.SetAttribute("sizeOnStartupMode", sizeOnStartupMode);
|
||||
propElement.SetAttribute("antialiasingMode", antialiasingMode);
|
||||
propElement.SetAttribute("antialisingEnabledOnMobile", isAntialisingEnabledOnMobile);
|
||||
propElement.SetAttribute("projectUuid", projectUuid);
|
||||
propElement.SetAttribute("folderProject", folderProject);
|
||||
propElement.SetAttribute("packageName", packageName);
|
||||
@@ -1113,6 +1119,8 @@ void Project::Init(const gd::Project& game) {
|
||||
pixelsRounding = game.pixelsRounding;
|
||||
adaptGameResolutionAtRuntime = game.adaptGameResolutionAtRuntime;
|
||||
sizeOnStartupMode = game.sizeOnStartupMode;
|
||||
antialiasingMode = game.antialiasingMode;
|
||||
isAntialisingEnabledOnMobile = game.isAntialisingEnabledOnMobile;
|
||||
projectUuid = game.projectUuid;
|
||||
useDeprecatedZeroAsDefaultZOrder = game.useDeprecatedZeroAsDefaultZOrder;
|
||||
|
||||
|
@@ -383,6 +383,26 @@ class GD_CORE_API Project : public ObjectsContainer {
|
||||
*/
|
||||
void SetPixelsRounding(bool enable) { pixelsRounding = enable; }
|
||||
|
||||
/**
|
||||
* Return the antialiasing mode used by the game ("none" or "MSAA").
|
||||
*/
|
||||
const gd::String& GetAntialiasingMode() const { return antialiasingMode; }
|
||||
|
||||
/**
|
||||
* Set the antialiasing mode used by the game ("none" or "MSAA").
|
||||
*/
|
||||
void SetAntialiasingMode(const gd::String& antialiasingMode_) { antialiasingMode = antialiasingMode_; }
|
||||
|
||||
/**
|
||||
* Return true if antialising is enabled on mobiles.
|
||||
*/
|
||||
bool IsAntialisingEnabledOnMobile() const { return isAntialisingEnabledOnMobile; }
|
||||
|
||||
/**
|
||||
* Set whether antialising is enabled on mobiles or not.
|
||||
*/
|
||||
void SetAntialisingEnabledOnMobile(bool enable) { isAntialisingEnabledOnMobile = enable; }
|
||||
|
||||
/**
|
||||
* \brief Return if the project should set 0 as Z-order for objects created
|
||||
* from events (which is deprecated) - instead of the highest Z order that was
|
||||
@@ -1040,6 +1060,8 @@ class GD_CORE_API Project : public ObjectsContainer {
|
||||
gd::String
|
||||
sizeOnStartupMode; ///< How to adapt the game size to the screen. Can be
|
||||
///< "adaptWidth", "adaptHeight" or empty
|
||||
gd::String antialiasingMode;
|
||||
bool isAntialisingEnabledOnMobile;
|
||||
gd::String projectUuid; ///< UUID useful to identify the game in online
|
||||
///< services or database that would require it.
|
||||
bool useDeprecatedZeroAsDefaultZOrder; ///< If true, objects created from
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
|
||||
/**
|
||||
* \}
|
||||
*/
|
||||
|
@@ -0,0 +1 @@
|
||||
|
||||
|
@@ -108,19 +108,8 @@ namespace gdjs {
|
||||
this.setWidth(initialInstanceData.width);
|
||||
this.setHeight(initialInstanceData.height);
|
||||
}
|
||||
initialInstanceData.numberProperties.forEach((property) => {
|
||||
if (property.name === 'z') {
|
||||
this.setZ(property.value);
|
||||
} else if (property.name === 'depth') {
|
||||
if (initialInstanceData.customSize) {
|
||||
this.setDepth(property.value);
|
||||
}
|
||||
} else if (property.name === 'rotationX') {
|
||||
this.setRotationX(property.value);
|
||||
} else if (property.name === 'rotationY') {
|
||||
this.setRotationY(property.value);
|
||||
}
|
||||
});
|
||||
if (initialInstanceData.depth !== undefined)
|
||||
this.setDepth(initialInstanceData.depth);
|
||||
}
|
||||
|
||||
setX(x: float): void {
|
||||
|
20
Extensions/3D/CMakeLists.txt
Normal file
20
Extensions/3D/CMakeLists.txt
Normal file
@@ -0,0 +1,20 @@
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
cmake_policy(SET CMP0015 NEW)
|
||||
|
||||
project(Scene3D)
|
||||
gd_add_extension_includes()
|
||||
|
||||
#Defines
|
||||
###
|
||||
gd_add_extension_definitions(Scene3D)
|
||||
|
||||
#The targets
|
||||
###
|
||||
include_directories(.)
|
||||
file(GLOB source_files *.cpp *.h)
|
||||
gd_add_clang_utils(Scene3D "${source_files}")
|
||||
gd_add_extension_target(Scene3D "${source_files}")
|
||||
|
||||
#Linker files for the IDE extension
|
||||
###
|
||||
gd_extension_link_libraries(Scene3D)
|
106
Extensions/3D/HemisphereLight.ts
Normal file
106
Extensions/3D/HemisphereLight.ts
Normal file
@@ -0,0 +1,106 @@
|
||||
namespace gdjs {
|
||||
gdjs.PixiFiltersTools.registerFilterCreator(
|
||||
'Scene3D::HemisphereLight',
|
||||
new (class implements gdjs.PixiFiltersTools.FilterCreator {
|
||||
makeFilter(
|
||||
target: EffectsTarget,
|
||||
effectData: EffectData
|
||||
): gdjs.PixiFiltersTools.Filter {
|
||||
return new (class implements gdjs.PixiFiltersTools.Filter {
|
||||
light: THREE.HemisphereLight;
|
||||
rotationObject: THREE.Group;
|
||||
_isEnabled: boolean = false;
|
||||
top: string = 'Y-';
|
||||
elevation: float = 45;
|
||||
rotation: float = 0;
|
||||
|
||||
constructor() {
|
||||
this.light = new THREE.HemisphereLight();
|
||||
this.light.position.set(1, 0, 0);
|
||||
this.rotationObject = new THREE.Group();
|
||||
this.rotationObject.add(this.light);
|
||||
this.updateRotation();
|
||||
}
|
||||
|
||||
isEnabled(target: EffectsTarget): boolean {
|
||||
return this._isEnabled;
|
||||
}
|
||||
setEnabled(target: EffectsTarget, enabled: boolean): boolean {
|
||||
if (this._isEnabled === enabled) {
|
||||
return true;
|
||||
}
|
||||
if (enabled) {
|
||||
return this.applyEffect(target);
|
||||
} else {
|
||||
return this.removeEffect(target);
|
||||
}
|
||||
}
|
||||
applyEffect(target: EffectsTarget): boolean {
|
||||
const scene = target.get3DRendererObject() as
|
||||
| THREE.Scene
|
||||
| null
|
||||
| undefined;
|
||||
if (!scene) {
|
||||
return false;
|
||||
}
|
||||
scene.add(this.rotationObject);
|
||||
this._isEnabled = true;
|
||||
return true;
|
||||
}
|
||||
removeEffect(target: EffectsTarget): boolean {
|
||||
const scene = target.get3DRendererObject() as
|
||||
| THREE.Scene
|
||||
| null
|
||||
| undefined;
|
||||
if (!scene) {
|
||||
return false;
|
||||
}
|
||||
scene.remove(this.rotationObject);
|
||||
this._isEnabled = false;
|
||||
return true;
|
||||
}
|
||||
updatePreRender(target: gdjs.EffectsTarget): any {}
|
||||
updateDoubleParameter(parameterName: string, value: number): void {
|
||||
if (parameterName === 'intensity') {
|
||||
this.light.intensity = value;
|
||||
} else if (parameterName === 'elevation') {
|
||||
this.elevation = value;
|
||||
this.updateRotation();
|
||||
} else if (parameterName === 'rotation') {
|
||||
this.rotation = value;
|
||||
this.updateRotation();
|
||||
}
|
||||
}
|
||||
updateStringParameter(parameterName: string, value: string): void {
|
||||
if (parameterName === 'skyColor') {
|
||||
this.light.color = new THREE.Color(
|
||||
gdjs.PixiFiltersTools.rgbOrHexToHexNumber(value)
|
||||
);
|
||||
}
|
||||
if (parameterName === 'groundColor') {
|
||||
this.light.groundColor = new THREE.Color(
|
||||
gdjs.PixiFiltersTools.rgbOrHexToHexNumber(value)
|
||||
);
|
||||
}
|
||||
if (parameterName === 'top') {
|
||||
this.top = value;
|
||||
this.updateRotation();
|
||||
}
|
||||
}
|
||||
updateBooleanParameter(parameterName: string, value: boolean): void {}
|
||||
updateRotation() {
|
||||
if (this.top === 'Z+') {
|
||||
// 0° is a light from the right of the screen.
|
||||
this.rotationObject.rotation.z = gdjs.toRad(this.rotation);
|
||||
this.rotationObject.rotation.y = -gdjs.toRad(this.elevation);
|
||||
} else {
|
||||
// 0° becomes a light from Z+.
|
||||
this.rotationObject.rotation.y = gdjs.toRad(this.rotation) - 90;
|
||||
this.rotationObject.rotation.z = -gdjs.toRad(this.elevation);
|
||||
}
|
||||
}
|
||||
})();
|
||||
}
|
||||
})()
|
||||
);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
292
Extensions/3D/Model3DObjectConfiguration.cpp
Normal file
292
Extensions/3D/Model3DObjectConfiguration.cpp
Normal file
@@ -0,0 +1,292 @@
|
||||
/**
|
||||
|
||||
GDevelop - Particle System Extension
|
||||
Copyright (c) 2010-2016 Florian Rival (Florian.Rival@gmail.com)
|
||||
This project is released under the MIT License.
|
||||
*/
|
||||
|
||||
#include "Model3DObjectConfiguration.h"
|
||||
|
||||
#include "GDCore/CommonTools.h"
|
||||
#include "GDCore/IDE/Project/ArbitraryResourceWorker.h"
|
||||
#include "GDCore/Project/InitialInstance.h"
|
||||
#include "GDCore/Project/MeasurementUnit.h"
|
||||
#include "GDCore/Project/Object.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/Project/PropertyDescriptor.h"
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
#include "GDCore/Tools/Localization.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
Model3DObjectConfiguration::Model3DObjectConfiguration()
|
||||
: width(100), height(100), depth(100), rotationX(0), rotationY(0),
|
||||
rotationZ(0), modelResourceName(""), materialType("Basic"),
|
||||
originLocation("ModelOrigin"), centerLocation("ModelOrigin"),
|
||||
keepAspectRatio(true) {}
|
||||
|
||||
bool Model3DObjectConfiguration::UpdateProperty(const gd::String &propertyName,
|
||||
const gd::String &newValue) {
|
||||
if (propertyName == "width") {
|
||||
width = newValue.To<double>();
|
||||
return true;
|
||||
}
|
||||
if (propertyName == "height") {
|
||||
height = newValue.To<double>();
|
||||
return true;
|
||||
}
|
||||
if (propertyName == "depth") {
|
||||
depth = newValue.To<double>();
|
||||
return true;
|
||||
}
|
||||
if (propertyName == "rotationX") {
|
||||
rotationX = newValue.To<double>();
|
||||
return true;
|
||||
}
|
||||
if (propertyName == "rotationY") {
|
||||
rotationY = newValue.To<double>();
|
||||
return true;
|
||||
}
|
||||
if (propertyName == "rotationZ") {
|
||||
rotationZ = newValue.To<double>();
|
||||
return true;
|
||||
}
|
||||
if (propertyName == "modelResourceName") {
|
||||
modelResourceName = newValue;
|
||||
return true;
|
||||
}
|
||||
if (propertyName == "materialType") {
|
||||
materialType = newValue;
|
||||
return true;
|
||||
}
|
||||
if (propertyName == "originLocation") {
|
||||
originLocation = newValue;
|
||||
return true;
|
||||
}
|
||||
if (propertyName == "centerLocation") {
|
||||
centerLocation = newValue;
|
||||
return true;
|
||||
}
|
||||
if (propertyName == "keepAspectRatio") {
|
||||
keepAspectRatio = newValue == "1";
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::map<gd::String, gd::PropertyDescriptor>
|
||||
Model3DObjectConfiguration::GetProperties() const {
|
||||
std::map<gd::String, gd::PropertyDescriptor> objectProperties;
|
||||
|
||||
objectProperties["width"]
|
||||
.SetValue(gd::String::From(width))
|
||||
.SetType("number")
|
||||
.SetLabel(_("Width"))
|
||||
.SetMeasurementUnit(gd::MeasurementUnit::GetPixel())
|
||||
.SetGroup(_("Default size"));
|
||||
|
||||
objectProperties["height"]
|
||||
.SetValue(gd::String::From(height))
|
||||
.SetType("number")
|
||||
.SetLabel(_("Height"))
|
||||
.SetMeasurementUnit(gd::MeasurementUnit::GetPixel())
|
||||
.SetGroup(_("Default size"));
|
||||
|
||||
objectProperties["depth"]
|
||||
.SetValue(gd::String::From(depth))
|
||||
.SetType("number")
|
||||
.SetLabel(_("Depth"))
|
||||
.SetMeasurementUnit(gd::MeasurementUnit::GetPixel())
|
||||
.SetGroup(_("Default size"));
|
||||
|
||||
objectProperties["keepAspectRatio"]
|
||||
.SetValue(keepAspectRatio ? "true" : "false")
|
||||
.SetType("boolean")
|
||||
.SetLabel(_("Reduce initial dimensions to keep aspect ratio"))
|
||||
.SetGroup(_("Default size"));
|
||||
|
||||
objectProperties["rotationX"]
|
||||
.SetValue(gd::String::From(rotationX))
|
||||
.SetType("number")
|
||||
.SetLabel(_("Rotation around X axis"))
|
||||
.SetMeasurementUnit(gd::MeasurementUnit::GetDegreeAngle())
|
||||
.SetGroup(_("Default orientation"));
|
||||
|
||||
objectProperties["rotationY"]
|
||||
.SetValue(gd::String::From(rotationY))
|
||||
.SetType("number")
|
||||
.SetLabel(_("Rotation around Y axis"))
|
||||
.SetMeasurementUnit(gd::MeasurementUnit::GetDegreeAngle())
|
||||
.SetGroup(_("Default orientation"));
|
||||
|
||||
objectProperties["rotationZ"]
|
||||
.SetValue(gd::String::From(rotationZ))
|
||||
.SetType("number")
|
||||
.SetLabel(_("Rotation around Z axis"))
|
||||
.SetMeasurementUnit(gd::MeasurementUnit::GetDegreeAngle())
|
||||
.SetGroup(_("Default orientation"));
|
||||
|
||||
objectProperties["modelResourceName"]
|
||||
.SetValue(modelResourceName)
|
||||
.SetType("resource")
|
||||
.AddExtraInfo("model3D")
|
||||
.SetLabel(_("3D model"));
|
||||
|
||||
objectProperties["materialType"]
|
||||
.SetValue(materialType.empty() ? "Basic" : materialType)
|
||||
.SetType("choice")
|
||||
.AddExtraInfo("Basic")
|
||||
.AddExtraInfo("StandardWithoutMetalness")
|
||||
.AddExtraInfo("KeepOriginal")
|
||||
.SetLabel(_("Material modifier"));
|
||||
|
||||
objectProperties["originLocation"]
|
||||
.SetValue(originLocation.empty() ? "TopLeft" : originLocation)
|
||||
.SetType("choice")
|
||||
.AddExtraInfo("ModelOrigin")
|
||||
.AddExtraInfo("TopLeft")
|
||||
.AddExtraInfo("ObjectCenter")
|
||||
.AddExtraInfo("BottomCenterZ")
|
||||
.AddExtraInfo("BottomCenterY")
|
||||
.SetLabel(_("Origin point"));
|
||||
|
||||
objectProperties["centerLocation"]
|
||||
.SetValue(centerLocation.empty() ? "ObjectCenter" : centerLocation)
|
||||
.SetType("choice")
|
||||
.AddExtraInfo("ModelOrigin")
|
||||
.AddExtraInfo("ObjectCenter")
|
||||
.AddExtraInfo("BottomCenterZ")
|
||||
.AddExtraInfo("BottomCenterY")
|
||||
.SetLabel(_("Center point"));
|
||||
|
||||
return objectProperties;
|
||||
}
|
||||
|
||||
bool Model3DObjectConfiguration::UpdateInitialInstanceProperty(
|
||||
gd::InitialInstance &instance, const gd::String &propertyName,
|
||||
const gd::String &newValue, gd::Project &project, gd::Layout &layout) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::map<gd::String, gd::PropertyDescriptor>
|
||||
Model3DObjectConfiguration::GetInitialInstanceProperties(
|
||||
const gd::InitialInstance &instance, gd::Project &project,
|
||||
gd::Layout &layout) {
|
||||
std::map<gd::String, gd::PropertyDescriptor> instanceProperties;
|
||||
return instanceProperties;
|
||||
}
|
||||
|
||||
void Model3DObjectConfiguration::DoUnserializeFrom(
|
||||
gd::Project &project, const gd::SerializerElement &element) {
|
||||
auto &content = element.GetChild("content");
|
||||
|
||||
width = content.GetDoubleAttribute("width");
|
||||
height = content.GetDoubleAttribute("height");
|
||||
depth = content.GetDoubleAttribute("depth");
|
||||
rotationX = content.GetDoubleAttribute("rotationX");
|
||||
rotationY = content.GetDoubleAttribute("rotationY");
|
||||
rotationZ = content.GetDoubleAttribute("rotationZ");
|
||||
modelResourceName = content.GetStringAttribute("modelResourceName");
|
||||
materialType = content.GetStringAttribute("materialType");
|
||||
originLocation = content.GetStringAttribute("originLocation");
|
||||
centerLocation = content.GetStringAttribute("centerLocation");
|
||||
keepAspectRatio = content.GetBoolAttribute("keepAspectRatio");
|
||||
|
||||
RemoveAllAnimations();
|
||||
auto &animationsElement = content.GetChild("animations");
|
||||
animationsElement.ConsiderAsArrayOf("animation");
|
||||
for (std::size_t i = 0; i < animationsElement.GetChildrenCount(); ++i) {
|
||||
auto &animationElement = animationsElement.GetChild(i);
|
||||
Model3DAnimation animation;
|
||||
animation.SetName(animationElement.GetStringAttribute("name", ""));
|
||||
animation.SetSource(animationElement.GetStringAttribute("source", ""));
|
||||
animation.SetShouldLoop(animationElement.GetBoolAttribute("loop", false));
|
||||
AddAnimation(animation);
|
||||
}
|
||||
}
|
||||
|
||||
void Model3DObjectConfiguration::DoSerializeTo(
|
||||
gd::SerializerElement &element) const {
|
||||
auto &content = element.AddChild("content");
|
||||
content.SetAttribute("width", width);
|
||||
content.SetAttribute("height", height);
|
||||
content.SetAttribute("depth", depth);
|
||||
content.SetAttribute("rotationX", rotationX);
|
||||
content.SetAttribute("rotationY", rotationY);
|
||||
content.SetAttribute("rotationZ", rotationZ);
|
||||
content.SetAttribute("modelResourceName", modelResourceName);
|
||||
content.SetAttribute("materialType", materialType);
|
||||
content.SetAttribute("originLocation", originLocation);
|
||||
content.SetAttribute("centerLocation", centerLocation);
|
||||
content.SetAttribute("keepAspectRatio", keepAspectRatio);
|
||||
|
||||
auto &animationsElement = content.AddChild("animations");
|
||||
animationsElement.ConsiderAsArrayOf("animation");
|
||||
for (auto &animation : animations) {
|
||||
auto &animationElement = animationsElement.AddChild("animation");
|
||||
animationElement.SetAttribute("name", animation.GetName());
|
||||
animationElement.SetAttribute("source", animation.GetSource());
|
||||
animationElement.SetAttribute("loop", animation.ShouldLoop());
|
||||
}
|
||||
}
|
||||
|
||||
void Model3DObjectConfiguration::ExposeResources(
|
||||
gd::ArbitraryResourceWorker &worker) {
|
||||
worker.ExposeModel3D(modelResourceName);
|
||||
}
|
||||
|
||||
Model3DAnimation Model3DObjectConfiguration::badAnimation;
|
||||
|
||||
const Model3DAnimation &
|
||||
Model3DObjectConfiguration::GetAnimation(std::size_t nb) const {
|
||||
if (nb >= animations.size())
|
||||
return badAnimation;
|
||||
|
||||
return animations[nb];
|
||||
}
|
||||
|
||||
Model3DAnimation &Model3DObjectConfiguration::GetAnimation(std::size_t nb) {
|
||||
if (nb >= animations.size())
|
||||
return badAnimation;
|
||||
|
||||
return animations[nb];
|
||||
}
|
||||
|
||||
bool Model3DObjectConfiguration::HasAnimationNamed(
|
||||
const gd::String &name) const {
|
||||
return !name.empty() && (find_if(animations.begin(), animations.end(),
|
||||
[&name](const Model3DAnimation &animation) {
|
||||
return animation.GetName() == name;
|
||||
}) != animations.end());
|
||||
}
|
||||
|
||||
void Model3DObjectConfiguration::AddAnimation(
|
||||
const Model3DAnimation &animation) {
|
||||
animations.push_back(animation);
|
||||
}
|
||||
|
||||
bool Model3DObjectConfiguration::RemoveAnimation(std::size_t nb) {
|
||||
if (nb >= GetAnimationsCount())
|
||||
return false;
|
||||
|
||||
animations.erase(animations.begin() + nb);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Model3DObjectConfiguration::SwapAnimations(std::size_t firstIndex,
|
||||
std::size_t secondIndex) {
|
||||
if (firstIndex < animations.size() && secondIndex < animations.size() &&
|
||||
firstIndex != secondIndex)
|
||||
std::swap(animations[firstIndex], animations[secondIndex]);
|
||||
}
|
||||
|
||||
void Model3DObjectConfiguration::MoveAnimation(std::size_t oldIndex,
|
||||
std::size_t newIndex) {
|
||||
if (oldIndex >= animations.size() || newIndex >= animations.size())
|
||||
return;
|
||||
|
||||
auto animation = animations[oldIndex];
|
||||
animations.erase(animations.begin() + oldIndex);
|
||||
animations.insert(animations.begin() + newIndex, animation);
|
||||
}
|
177
Extensions/3D/Model3DObjectConfiguration.h
Normal file
177
Extensions/3D/Model3DObjectConfiguration.h
Normal file
@@ -0,0 +1,177 @@
|
||||
/**
|
||||
|
||||
GDevelop - Particle System Extension
|
||||
Copyright (c) 2010-2016 Florian Rival (Florian.Rival@gmail.com)
|
||||
This project is released under the MIT License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GDCore/Project/ObjectConfiguration.h"
|
||||
namespace gd {
|
||||
class InitialInstance;
|
||||
class Project;
|
||||
} // namespace gd
|
||||
|
||||
class GD_EXTENSION_API Model3DAnimation {
|
||||
public:
|
||||
Model3DAnimation() : shouldLoop(false) {};
|
||||
virtual ~Model3DAnimation(){};
|
||||
|
||||
/**
|
||||
* \brief Return the name of the animation
|
||||
*/
|
||||
const gd::String &GetName() const { return name; }
|
||||
|
||||
/**
|
||||
* \brief Change the name of the animation
|
||||
*/
|
||||
void SetName(const gd::String &name_) { name = name_; }
|
||||
|
||||
/**
|
||||
* \brief Return the name of the animation from the GLB file.
|
||||
*/
|
||||
const gd::String &GetSource() const { return source; }
|
||||
|
||||
/**
|
||||
* \brief Change the name of the animation from the GLB file.
|
||||
*/
|
||||
void SetSource(const gd::String &source_) { source = source_; }
|
||||
|
||||
/**
|
||||
* \brief Return true if the animation should loop.
|
||||
*/
|
||||
const bool ShouldLoop() const { return shouldLoop; }
|
||||
|
||||
/**
|
||||
* \brief Change whether the animation should loop or not.
|
||||
*/
|
||||
void SetShouldLoop(bool shouldLoop_) { shouldLoop = shouldLoop_; }
|
||||
|
||||
private:
|
||||
gd::String name;
|
||||
gd::String source;
|
||||
bool shouldLoop;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Particle Emitter object used for storage and for the IDE.
|
||||
*/
|
||||
class GD_EXTENSION_API Model3DObjectConfiguration
|
||||
: public gd::ObjectConfiguration {
|
||||
public:
|
||||
Model3DObjectConfiguration();
|
||||
virtual ~Model3DObjectConfiguration(){};
|
||||
virtual std::unique_ptr<gd::ObjectConfiguration> Clone() const override {
|
||||
return gd::make_unique<Model3DObjectConfiguration>(*this);
|
||||
}
|
||||
|
||||
virtual void ExposeResources(gd::ArbitraryResourceWorker &worker) override;
|
||||
|
||||
virtual std::map<gd::String, gd::PropertyDescriptor>
|
||||
GetProperties() const override;
|
||||
|
||||
virtual bool UpdateProperty(const gd::String &name,
|
||||
const gd::String &value) override;
|
||||
|
||||
virtual std::map<gd::String, gd::PropertyDescriptor>
|
||||
GetInitialInstanceProperties(const gd::InitialInstance &instance,
|
||||
gd::Project &project,
|
||||
gd::Layout &layout) override;
|
||||
|
||||
virtual bool UpdateInitialInstanceProperty(gd::InitialInstance &instance,
|
||||
const gd::String &name,
|
||||
const gd::String &value,
|
||||
gd::Project &project,
|
||||
gd::Layout &layout) override;
|
||||
|
||||
/** \name Animations
|
||||
* Methods related to animations management
|
||||
*/
|
||||
///@{
|
||||
/**
|
||||
* \brief Return the animation at the specified index.
|
||||
* If the index is out of bound, a "bad animation" object is returned.
|
||||
*/
|
||||
const Model3DAnimation &GetAnimation(std::size_t nb) const;
|
||||
|
||||
/**
|
||||
* \brief Return the animation at the specified index.
|
||||
* If the index is out of bound, a "bad animation" object is returned.
|
||||
*/
|
||||
Model3DAnimation &GetAnimation(std::size_t nb);
|
||||
|
||||
/**
|
||||
* \brief Return the number of animations this object has.
|
||||
*/
|
||||
std::size_t GetAnimationsCount() const { return animations.size(); };
|
||||
|
||||
/**
|
||||
* \brief Return true if the animation called "name" exists.
|
||||
*/
|
||||
bool HasAnimationNamed(const gd::String& name) const;
|
||||
|
||||
/**
|
||||
* \brief Add an animation at the end of the existing ones.
|
||||
*/
|
||||
void AddAnimation(const Model3DAnimation &animation);
|
||||
|
||||
/**
|
||||
* \brief Remove an animation.
|
||||
*/
|
||||
bool RemoveAnimation(std::size_t nb);
|
||||
|
||||
/**
|
||||
* \brief Remove all animations.
|
||||
*/
|
||||
void RemoveAllAnimations() { animations.clear(); }
|
||||
|
||||
/**
|
||||
* \brief Return true if the object hasn't any animation.
|
||||
*/
|
||||
bool HasNoAnimations() const { return animations.empty(); }
|
||||
|
||||
/**
|
||||
* \brief Swap the position of two animations
|
||||
*/
|
||||
void SwapAnimations(std::size_t firstIndex, std::size_t secondIndex);
|
||||
|
||||
/**
|
||||
* \brief Change the position of the specified animation
|
||||
*/
|
||||
void MoveAnimation(std::size_t oldIndex, std::size_t newIndex);
|
||||
|
||||
/**
|
||||
* \brief Return a read-only reference to the vector containing all the
|
||||
* animation of the object.
|
||||
*/
|
||||
const std::vector<Model3DAnimation> &GetAllAnimations() const {
|
||||
return animations;
|
||||
}
|
||||
|
||||
///@}
|
||||
|
||||
protected:
|
||||
virtual void DoUnserializeFrom(gd::Project &project,
|
||||
const gd::SerializerElement &element) override;
|
||||
virtual void DoSerializeTo(gd::SerializerElement &element) const override;
|
||||
|
||||
private:
|
||||
double width;
|
||||
double height;
|
||||
double depth;
|
||||
double rotationX;
|
||||
double rotationY;
|
||||
double rotationZ;
|
||||
|
||||
gd::String modelResourceName;
|
||||
gd::String materialType;
|
||||
gd::String originLocation;
|
||||
gd::String centerLocation;
|
||||
|
||||
bool keepAspectRatio;
|
||||
|
||||
std::vector<Model3DAnimation> animations;
|
||||
static Model3DAnimation badAnimation; //< Bad animation when an out of bound
|
||||
// animation is requested.
|
||||
};
|
@@ -1,4 +1,6 @@
|
||||
namespace gdjs {
|
||||
type Model3DAnimation = { name: string; source: string; loop: boolean };
|
||||
|
||||
/** Base parameters for {@link gdjs.Cube3DRuntimeObject} */
|
||||
export interface Model3DObjectData extends Object3DData {
|
||||
/** The base parameters of the Model3D object */
|
||||
@@ -9,9 +11,40 @@ namespace gdjs {
|
||||
rotationZ: number;
|
||||
keepAspectRatio: boolean;
|
||||
materialType: 'Basic' | 'StandardWithoutMetalness' | 'KeepOriginal';
|
||||
originLocation:
|
||||
| 'ModelOrigin'
|
||||
| 'ObjectCenter'
|
||||
| 'BottomCenterZ'
|
||||
| 'BottomCenterY'
|
||||
| 'TopLeft';
|
||||
centerLocation:
|
||||
| 'ModelOrigin'
|
||||
| 'ObjectCenter'
|
||||
| 'BottomCenterZ'
|
||||
| 'BottomCenterY';
|
||||
animations: Model3DAnimation[];
|
||||
};
|
||||
}
|
||||
|
||||
type FloatPoint3D = [float, float, float];
|
||||
|
||||
const getPointForLocation = (location: string): FloatPoint3D | null => {
|
||||
switch (location) {
|
||||
case 'ModelOrigin':
|
||||
return null;
|
||||
case 'ObjectCenter':
|
||||
return [0.5, 0.5, 0.5];
|
||||
case 'BottomCenterZ':
|
||||
return [0.5, 0.5, 0];
|
||||
case 'BottomCenterY':
|
||||
return [0.5, 1, 0.5];
|
||||
case 'TopLeft':
|
||||
return [0, 0, 0];
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* A 3D object which displays a 3D model.
|
||||
*/
|
||||
@@ -22,17 +55,61 @@ namespace gdjs {
|
||||
_materialType: gdjs.Model3DRuntimeObject.MaterialType =
|
||||
gdjs.Model3DRuntimeObject.MaterialType.Basic;
|
||||
|
||||
/**
|
||||
* The local point of the model that will be at the object position.
|
||||
*
|
||||
* Coordinates are between 0 and 1.
|
||||
*
|
||||
* Its value is `null` when the point is configured to `"ModelOrigin"`
|
||||
* because the model origin needs to be evaluated according to the object
|
||||
* configuration.
|
||||
* @see gdjs.Model3DRuntimeObject3DRenderer.getOriginPoint
|
||||
*/
|
||||
_originPoint: FloatPoint3D | null;
|
||||
/**
|
||||
* The local point of the model that is used as rotation center.
|
||||
*
|
||||
* Coordinates are between 0 and 1.
|
||||
*
|
||||
* Its value is `null` when the point is configured to `"ModelOrigin"`
|
||||
* because the model origin needs to be evaluated according to the object
|
||||
* configuration.
|
||||
* @see gdjs.Model3DRuntimeObject3DRenderer.getCenterPoint
|
||||
*/
|
||||
_centerPoint: FloatPoint3D | null;
|
||||
|
||||
_animations: Model3DAnimation[];
|
||||
_currentAnimationIndex: integer = 0;
|
||||
_animationSpeedScale: float = 1;
|
||||
_animationPaused: boolean = false;
|
||||
|
||||
constructor(
|
||||
instanceContainer: gdjs.RuntimeInstanceContainer,
|
||||
objectData: Model3DObjectData
|
||||
) {
|
||||
super(instanceContainer, objectData);
|
||||
this._modelResourceName = objectData.content.modelResourceName;
|
||||
this._animations = objectData.content.animations;
|
||||
this._originPoint = getPointForLocation(
|
||||
objectData.content.originLocation
|
||||
);
|
||||
this._centerPoint = getPointForLocation(
|
||||
objectData.content.centerLocation
|
||||
);
|
||||
this._renderer = new gdjs.Model3DRuntimeObjectRenderer(
|
||||
this,
|
||||
instanceContainer
|
||||
);
|
||||
this._updateMaterialType(objectData);
|
||||
this._materialType = this._convertMaterialType(
|
||||
objectData.content.materialType
|
||||
);
|
||||
this._updateModel(objectData);
|
||||
if (this._animations.length > 0) {
|
||||
this._renderer.playAnimation(
|
||||
this._animations[0].source,
|
||||
this._animations[0].loop
|
||||
);
|
||||
}
|
||||
|
||||
// *ALWAYS* call `this.onCreated()` at the very end of your object constructor.
|
||||
this.onCreated();
|
||||
@@ -53,23 +130,42 @@ namespace gdjs {
|
||||
oldObjectData.content.keepAspectRatio !==
|
||||
newObjectData.content.keepAspectRatio
|
||||
) {
|
||||
this._updateDefaultTransformation(newObjectData);
|
||||
this._updateModel(newObjectData);
|
||||
}
|
||||
if (
|
||||
oldObjectData.content.materialType !==
|
||||
newObjectData.content.materialType
|
||||
) {
|
||||
this._updateMaterialType(newObjectData);
|
||||
this._materialType = this._convertMaterialType(
|
||||
newObjectData.content.materialType
|
||||
);
|
||||
this._updateModel(newObjectData);
|
||||
}
|
||||
if (
|
||||
oldObjectData.content.originLocation !==
|
||||
newObjectData.content.originLocation
|
||||
) {
|
||||
this._originPoint = getPointForLocation(
|
||||
newObjectData.content.originLocation
|
||||
);
|
||||
}
|
||||
if (
|
||||
oldObjectData.content.centerLocation !==
|
||||
newObjectData.content.centerLocation
|
||||
) {
|
||||
this._centerPoint = getPointForLocation(
|
||||
newObjectData.content.centerLocation
|
||||
);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
_updateDefaultTransformation(objectData: Model3DObjectData) {
|
||||
_updateModel(objectData: Model3DObjectData) {
|
||||
const rotationX = objectData.content.rotationX || 0;
|
||||
const rotationY = objectData.content.rotationY || 0;
|
||||
const rotationZ = objectData.content.rotationZ || 0;
|
||||
const keepAspectRatio = objectData.content.keepAspectRatio;
|
||||
this._renderer._updateDefaultTransformation(
|
||||
this._renderer._updateModel(
|
||||
rotationX,
|
||||
rotationY,
|
||||
rotationZ,
|
||||
@@ -96,12 +192,118 @@ namespace gdjs {
|
||||
}
|
||||
}
|
||||
|
||||
_updateMaterialType(objectData: Model3DObjectData) {
|
||||
this._materialType = this._convertMaterialType(
|
||||
objectData.content.materialType
|
||||
update(instanceContainer: gdjs.RuntimeInstanceContainer): void {
|
||||
const elapsedTime = this.getElapsedTime() / 1000;
|
||||
this._renderer.updateAnimation(elapsedTime * this._animationSpeedScale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the index of the animation being played.
|
||||
* @return The index of the new animation being played
|
||||
*/
|
||||
getAnimationIndex(): number {
|
||||
return this._currentAnimationIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the animation being played.
|
||||
* @param animationIndex The index of the new animation to be played
|
||||
*/
|
||||
setAnimationIndex(animationIndex: number): void {
|
||||
animationIndex = animationIndex | 0;
|
||||
if (
|
||||
animationIndex < this._animations.length &&
|
||||
this._currentAnimationIndex !== animationIndex &&
|
||||
animationIndex >= 0
|
||||
) {
|
||||
const animation = this._animations[animationIndex];
|
||||
this._currentAnimationIndex = animationIndex;
|
||||
this._renderer.playAnimation(animation.source, animation.loop);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the animation being played.
|
||||
* @return The name of the new animation being played
|
||||
*/
|
||||
getAnimationName(): string {
|
||||
if (this._currentAnimationIndex >= this._animations.length) {
|
||||
return '';
|
||||
}
|
||||
return this._animations[this._currentAnimationIndex].name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the animation being played.
|
||||
* @param newAnimationName The name of the new animation to be played
|
||||
*/
|
||||
setAnimationName(newAnimationName: string): void {
|
||||
if (!newAnimationName) {
|
||||
return;
|
||||
}
|
||||
const animationIndex = this._animations.findIndex(
|
||||
(animation) => animation.name === newAnimationName
|
||||
);
|
||||
this._renderer._updateMaterials();
|
||||
this._updateDefaultTransformation(objectData);
|
||||
if (animationIndex >= 0) {
|
||||
this.setAnimationIndex(animationIndex);
|
||||
}
|
||||
}
|
||||
|
||||
isCurrentAnimationName(name: string): boolean {
|
||||
return this.getAnimationName() === name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if animation has ended.
|
||||
* The animation had ended if:
|
||||
* - it's not configured as a loop;
|
||||
* - the current frame is the last frame;
|
||||
* - the last frame has been displayed long enough.
|
||||
*/
|
||||
hasAnimationEnded(): boolean {
|
||||
return this._renderer.hasAnimationEnded();
|
||||
}
|
||||
|
||||
isAnimationPaused() {
|
||||
return this._animationPaused;
|
||||
}
|
||||
|
||||
pauseAnimation() {
|
||||
this._animationPaused = true;
|
||||
return this._renderer.pauseAnimation();
|
||||
}
|
||||
|
||||
resumeAnimation() {
|
||||
this._animationPaused = false;
|
||||
return this._renderer.resumeAnimation();
|
||||
}
|
||||
|
||||
getAnimationSpeedScale() {
|
||||
return this._animationSpeedScale;
|
||||
}
|
||||
|
||||
setAnimationSpeedScale(ratio: float): void {
|
||||
this._animationSpeedScale = ratio;
|
||||
}
|
||||
|
||||
getCenterX(): float {
|
||||
const centerPoint = this._renderer.getCenterPoint();
|
||||
return this.getWidth() * centerPoint[0];
|
||||
}
|
||||
|
||||
getCenterY(): float {
|
||||
const centerPoint = this._renderer.getCenterPoint();
|
||||
return this.getHeight() * centerPoint[1];
|
||||
}
|
||||
|
||||
getDrawableX(): float {
|
||||
const originPoint = this._renderer.getOriginPoint();
|
||||
return this.getX() - this.getWidth() * originPoint[0];
|
||||
}
|
||||
|
||||
getDrawableY(): float {
|
||||
const originPoint = this._renderer.getOriginPoint();
|
||||
return this.getY() - this.getHeight() * originPoint[1];
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,38 +1,144 @@
|
||||
namespace gdjs {
|
||||
type FloatPoint3D = [float, float, float];
|
||||
|
||||
const removeMetalness = (material: THREE.Material): void => {
|
||||
//@ts-ignore
|
||||
if (material.metalness) {
|
||||
//@ts-ignore
|
||||
material.metalness = 0;
|
||||
}
|
||||
};
|
||||
|
||||
const removeMetalnessFromMesh = (node: THREE.Object3D<THREE.Event>) => {
|
||||
const mesh = node as THREE.Mesh;
|
||||
if (!mesh.material) {
|
||||
return;
|
||||
}
|
||||
if (Array.isArray(mesh.material)) {
|
||||
for (let index = 0; index < mesh.material.length; index++) {
|
||||
removeMetalness(mesh.material[index]);
|
||||
}
|
||||
} else {
|
||||
removeMetalness(mesh.material);
|
||||
}
|
||||
};
|
||||
|
||||
const traverseToRemoveMetalnessFromMeshes = (
|
||||
node: THREE.Object3D<THREE.Event>
|
||||
) => node.traverse(removeMetalnessFromMesh);
|
||||
|
||||
const convertToBasicMaterial = (
|
||||
material: THREE.Material
|
||||
): THREE.MeshBasicMaterial => {
|
||||
const basicMaterial = new THREE.MeshBasicMaterial();
|
||||
//@ts-ignore
|
||||
if (material.color) {
|
||||
//@ts-ignore
|
||||
basicMaterial.color = material.color;
|
||||
}
|
||||
//@ts-ignore
|
||||
if (material.map) {
|
||||
//@ts-ignore
|
||||
basicMaterial.map = material.map;
|
||||
}
|
||||
return basicMaterial;
|
||||
};
|
||||
|
||||
const setBasicMaterialTo = (node: THREE.Object3D<THREE.Event>): void => {
|
||||
const mesh = node as THREE.Mesh;
|
||||
if (!mesh.material) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Array.isArray(mesh.material)) {
|
||||
for (let index = 0; index < mesh.material.length; index++) {
|
||||
mesh.material[index] = convertToBasicMaterial(mesh.material[index]);
|
||||
}
|
||||
} else {
|
||||
mesh.material = convertToBasicMaterial(mesh.material);
|
||||
}
|
||||
};
|
||||
|
||||
const traverseToSetBasicMaterialFromMeshes = (
|
||||
node: THREE.Object3D<THREE.Event>
|
||||
) => node.traverse(setBasicMaterialTo);
|
||||
|
||||
class Model3DRuntimeObject3DRenderer extends gdjs.RuntimeObject3DRenderer {
|
||||
private _model3DRuntimeObject: gdjs.Model3DRuntimeObject;
|
||||
/**
|
||||
* The 3D model stretched in a 1x1x1 cube.
|
||||
*/
|
||||
private _threeObject: THREE.Object3D;
|
||||
private _originalModel: THREE_ADDONS.GLTF;
|
||||
private _animationMixer: THREE.AnimationMixer;
|
||||
private _action: THREE.AnimationAction | null;
|
||||
|
||||
/**
|
||||
* The model origin evaluated according to the object configuration.
|
||||
*
|
||||
* Coordinates are between 0 and 1.
|
||||
*/
|
||||
private _modelOriginPoint: FloatPoint3D;
|
||||
|
||||
constructor(
|
||||
runtimeObject: gdjs.Model3DRuntimeObject,
|
||||
instanceContainer: gdjs.RuntimeInstanceContainer
|
||||
) {
|
||||
// @ts-ignore It can't be null if THREE exists.
|
||||
const originalModelMesh: THREE.Object3D = instanceContainer
|
||||
// GLB files with skeleton must not have any transformation to work properly.
|
||||
const originalModel = instanceContainer
|
||||
.getGame()
|
||||
.getModel3DManager()
|
||||
.getModel(runtimeObject._modelResourceName);
|
||||
const modelObject3D = originalModelMesh.clone();
|
||||
// _updateModel will actually add a clone of the model.
|
||||
const model = new THREE.Group();
|
||||
|
||||
// Create a group to transform the object according to
|
||||
// position, angle and dimensions.
|
||||
const group = new THREE.Group();
|
||||
group.rotation.order = 'ZYX';
|
||||
group.add(modelObject3D);
|
||||
group.add(model);
|
||||
super(runtimeObject, instanceContainer, group);
|
||||
|
||||
this._model3DRuntimeObject = runtimeObject;
|
||||
this._threeObject = modelObject3D;
|
||||
this._threeObject = model;
|
||||
this._originalModel = originalModel;
|
||||
this._modelOriginPoint = [0, 0, 0];
|
||||
|
||||
this.updateSize();
|
||||
this.updatePosition();
|
||||
this.updateRotation();
|
||||
|
||||
this._animationMixer = new THREE.AnimationMixer(model);
|
||||
this._action = null;
|
||||
}
|
||||
|
||||
_updateDefaultTransformation(
|
||||
updateAnimation(timeDelta: float) {
|
||||
this._animationMixer.update(timeDelta);
|
||||
}
|
||||
|
||||
updatePosition() {
|
||||
const originPoint = this.getOriginPoint();
|
||||
const centerPoint = this.getCenterPoint();
|
||||
this.get3DRendererObject().position.set(
|
||||
this._object.getX() -
|
||||
this._object.getWidth() * (originPoint[0] - centerPoint[0]),
|
||||
this._object.getY() -
|
||||
this._object.getHeight() * (originPoint[1] - centerPoint[1]),
|
||||
this._object.getZ() -
|
||||
this._object.getDepth() * (originPoint[2] - centerPoint[2])
|
||||
);
|
||||
}
|
||||
|
||||
getOriginPoint() {
|
||||
return this._model3DRuntimeObject._originPoint || this._modelOriginPoint;
|
||||
}
|
||||
|
||||
getCenterPoint() {
|
||||
return this._model3DRuntimeObject._centerPoint || this._modelOriginPoint;
|
||||
}
|
||||
|
||||
private _updateDefaultTransformation(
|
||||
threeObject: THREE.Object3D,
|
||||
rotationX: float,
|
||||
rotationY: float,
|
||||
rotationZ: float,
|
||||
@@ -41,38 +147,63 @@ namespace gdjs {
|
||||
originalDepth: float,
|
||||
keepAspectRatio: boolean
|
||||
) {
|
||||
const boundingBox = this._getModelAABB(rotationX, rotationY, rotationZ);
|
||||
threeObject.rotation.set(
|
||||
gdjs.toRad(rotationX),
|
||||
gdjs.toRad(rotationY),
|
||||
gdjs.toRad(rotationZ)
|
||||
);
|
||||
threeObject.updateMatrixWorld(true);
|
||||
const boundingBox = new THREE.Box3().setFromObject(threeObject);
|
||||
|
||||
const modelWidth = boundingBox.max.x - boundingBox.min.x;
|
||||
const modelHeight = boundingBox.max.y - boundingBox.min.y;
|
||||
const modelDepth = boundingBox.max.z - boundingBox.min.z;
|
||||
this._modelOriginPoint[0] = -boundingBox.min.x / modelWidth;
|
||||
this._modelOriginPoint[1] = -boundingBox.min.y / modelHeight;
|
||||
this._modelOriginPoint[2] = -boundingBox.min.z / modelDepth;
|
||||
|
||||
// The model is flipped on Y axis.
|
||||
this._modelOriginPoint[1] = 1 - this._modelOriginPoint[1];
|
||||
|
||||
// Center the model.
|
||||
this._threeObject.position.set(
|
||||
-(boundingBox.min.x + boundingBox.max.x) / 2,
|
||||
(this._threeObject.position.y =
|
||||
-(boundingBox.min.y + boundingBox.max.y) / 2),
|
||||
(this._threeObject.position.z =
|
||||
-(boundingBox.min.z + boundingBox.max.z) / 2)
|
||||
);
|
||||
const centerPoint = this._model3DRuntimeObject._centerPoint;
|
||||
if (centerPoint) {
|
||||
threeObject.position.set(
|
||||
-(
|
||||
boundingBox.min.x +
|
||||
(boundingBox.max.x - boundingBox.min.x) * centerPoint[0]
|
||||
),
|
||||
// The model is flipped on Y axis.
|
||||
-(
|
||||
boundingBox.min.y +
|
||||
(boundingBox.max.y - boundingBox.min.y) * (1 - centerPoint[1])
|
||||
),
|
||||
-(
|
||||
boundingBox.min.z +
|
||||
(boundingBox.max.z - boundingBox.min.z) * centerPoint[2]
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Rotate the model.
|
||||
this._threeObject.scale.set(1, 1, 1);
|
||||
this._threeObject.rotation.set(
|
||||
threeObject.scale.set(1, 1, 1);
|
||||
threeObject.rotation.set(
|
||||
gdjs.toRad(rotationX),
|
||||
gdjs.toRad(rotationY),
|
||||
gdjs.toRad(rotationZ)
|
||||
);
|
||||
|
||||
// Stretch the model in a 1x1x1 cube.
|
||||
const modelWidth = boundingBox.max.x - boundingBox.min.x;
|
||||
const modelHeight = boundingBox.max.y - boundingBox.min.y;
|
||||
const modelDepth = boundingBox.max.z - boundingBox.min.z;
|
||||
|
||||
const scaleX = 1 / modelWidth;
|
||||
const scaleY = 1 / modelHeight;
|
||||
const scaleZ = 1 / modelDepth;
|
||||
|
||||
const scaleMatrix = new THREE.Matrix4();
|
||||
scaleMatrix.makeScale(scaleX, scaleY, scaleZ);
|
||||
this._threeObject.updateMatrix();
|
||||
this._threeObject.applyMatrix4(scaleMatrix);
|
||||
// Flip on Y because the Y axis is on the opposite side of direct basis.
|
||||
// It avoids models to be like a mirror refection.
|
||||
scaleMatrix.makeScale(scaleX, -scaleY, scaleZ);
|
||||
threeObject.updateMatrix();
|
||||
threeObject.applyMatrix4(scaleMatrix);
|
||||
|
||||
if (keepAspectRatio) {
|
||||
// Reduce the object dimensions to keep aspect ratio.
|
||||
@@ -85,98 +216,138 @@ namespace gdjs {
|
||||
this._object._setOriginalHeight(scaleRatio * modelHeight);
|
||||
this._object._setOriginalDepth(scaleRatio * modelDepth);
|
||||
}
|
||||
|
||||
this._threeObject.updateMatrix();
|
||||
}
|
||||
|
||||
private _getModelAABB(
|
||||
_updateModel(
|
||||
rotationX: float,
|
||||
rotationY: float,
|
||||
rotationZ: float
|
||||
rotationZ: float,
|
||||
originalWidth: float,
|
||||
originalHeight: float,
|
||||
originalDepth: float,
|
||||
keepAspectRatio: boolean
|
||||
) {
|
||||
// The original model is used because `setFromObject` is working in
|
||||
// world transformation.
|
||||
// Start from the original model because:
|
||||
// - _replaceMaterials is destructive
|
||||
// - _updateDefaultTransformation may need to work with meshes in local space
|
||||
|
||||
// @ts-ignore It can't be null if THREE exists.
|
||||
const originalModelMesh: THREE.Object3D = this._object
|
||||
.getInstanceContainer()
|
||||
.getGame()
|
||||
.getModel3DManager()
|
||||
.getModel(this._model3DRuntimeObject._modelResourceName);
|
||||
// This group hold the rotation defined by properties.
|
||||
const threeObject = new THREE.Group();
|
||||
threeObject.rotation.order = 'ZYX';
|
||||
const root = THREE_ADDONS.SkeletonUtils.clone(this._originalModel.scene);
|
||||
threeObject.add(root);
|
||||
|
||||
originalModelMesh.rotation.set(
|
||||
gdjs.toRad(rotationX),
|
||||
gdjs.toRad(rotationY),
|
||||
gdjs.toRad(rotationZ)
|
||||
this._replaceMaterials(threeObject);
|
||||
|
||||
this._updateDefaultTransformation(
|
||||
threeObject,
|
||||
rotationX,
|
||||
rotationY,
|
||||
rotationZ,
|
||||
originalWidth,
|
||||
originalHeight,
|
||||
originalDepth,
|
||||
keepAspectRatio
|
||||
);
|
||||
|
||||
const aabb = new THREE.Box3().setFromObject(originalModelMesh);
|
||||
|
||||
// Revert changes.
|
||||
originalModelMesh.rotation.set(0, 0, 0);
|
||||
|
||||
return aabb;
|
||||
}
|
||||
|
||||
_updateMaterials() {
|
||||
// @ts-ignore It can't be null if THREE exists.
|
||||
const originalModelMesh: THREE.Object3D = this._model3DRuntimeObject
|
||||
.getInstanceContainer()
|
||||
.getGame()
|
||||
.getModel3DManager()
|
||||
.getModel(this._model3DRuntimeObject._modelResourceName);
|
||||
const modelObject3D = originalModelMesh.clone();
|
||||
|
||||
// Replace the 3D object.
|
||||
this.get3DRendererObject().remove(this._threeObject);
|
||||
this.get3DRendererObject().add(modelObject3D);
|
||||
this.get3DRendererObject().add(threeObject);
|
||||
this._threeObject = threeObject;
|
||||
|
||||
this._threeObject = modelObject3D;
|
||||
|
||||
this._replaceMaterials();
|
||||
// Start the current animation on the new 3D object.
|
||||
this._animationMixer = new THREE.AnimationMixer(root);
|
||||
const isAnimationPaused = this._model3DRuntimeObject.isAnimationPaused();
|
||||
this._model3DRuntimeObject.setAnimationIndex(
|
||||
this._model3DRuntimeObject.getAnimationIndex()
|
||||
);
|
||||
if (isAnimationPaused) {
|
||||
this.pauseAnimation();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace materials to better work with lights (or no light).
|
||||
*/
|
||||
_replaceMaterials() {
|
||||
private _replaceMaterials(threeObject: THREE.Object3D) {
|
||||
if (
|
||||
this._model3DRuntimeObject._materialType ===
|
||||
gdjs.Model3DRuntimeObject.MaterialType.StandardWithoutMetalness
|
||||
) {
|
||||
this._threeObject.traverse((node) => {
|
||||
if (node.type === 'Mesh') {
|
||||
const mesh = node as THREE.Mesh;
|
||||
const material = mesh.material as THREE.MeshStandardMaterial;
|
||||
//@ts-ignore
|
||||
if (material.metalness) {
|
||||
//@ts-ignore
|
||||
material.metalness = 0;
|
||||
}
|
||||
}
|
||||
});
|
||||
traverseToRemoveMetalnessFromMeshes(threeObject);
|
||||
} else if (
|
||||
this._model3DRuntimeObject._materialType ===
|
||||
gdjs.Model3DRuntimeObject.MaterialType.Basic
|
||||
) {
|
||||
this._threeObject.traverse((node) => {
|
||||
if (node.type === 'Mesh') {
|
||||
const mesh = node as THREE.Mesh;
|
||||
const basicMaterial = new THREE.MeshBasicMaterial();
|
||||
//@ts-ignore
|
||||
if (mesh.material.color) {
|
||||
//@ts-ignore
|
||||
basicMaterial.color = mesh.material.color;
|
||||
}
|
||||
//@ts-ignore
|
||||
if (mesh.material.map) {
|
||||
//@ts-ignore
|
||||
basicMaterial.map = mesh.material.map;
|
||||
}
|
||||
mesh.material = basicMaterial;
|
||||
}
|
||||
});
|
||||
traverseToSetBasicMaterialFromMeshes(threeObject);
|
||||
}
|
||||
}
|
||||
|
||||
getAnimationCount() {
|
||||
return this._originalModel.animations.length;
|
||||
}
|
||||
|
||||
getAnimationName(animationIndex: integer) {
|
||||
return this._originalModel.animations[animationIndex].name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if animation has ended.
|
||||
* The animation had ended if:
|
||||
* - it's not configured as a loop;
|
||||
* - the current frame is the last frame;
|
||||
* - the last frame has been displayed long enough.
|
||||
*/
|
||||
hasAnimationEnded(): boolean {
|
||||
if (!this._action) {
|
||||
return true;
|
||||
}
|
||||
return !this._action.isRunning();
|
||||
}
|
||||
|
||||
animationPaused() {
|
||||
if (!this._action) {
|
||||
return;
|
||||
}
|
||||
return this._action.paused;
|
||||
}
|
||||
|
||||
pauseAnimation() {
|
||||
if (!this._action) {
|
||||
return;
|
||||
}
|
||||
this._action.paused = true;
|
||||
}
|
||||
|
||||
resumeAnimation() {
|
||||
if (!this._action) {
|
||||
return;
|
||||
}
|
||||
this._action.paused = false;
|
||||
}
|
||||
|
||||
playAnimation(animationName: string, shouldLoop: boolean) {
|
||||
this._animationMixer.stopAllAction();
|
||||
const clip = THREE.AnimationClip.findByName(
|
||||
this._originalModel.animations,
|
||||
animationName
|
||||
);
|
||||
if (!clip) {
|
||||
console.error(
|
||||
`The GLB file: ${this._model3DRuntimeObject._modelResourceName} doesn't have any animation named: ${animationName}`
|
||||
);
|
||||
return;
|
||||
}
|
||||
this._action = this._animationMixer.clipAction(clip);
|
||||
this._action.setLoop(
|
||||
shouldLoop ? THREE.LoopRepeat : THREE.LoopOnce,
|
||||
Number.POSITIVE_INFINITY
|
||||
);
|
||||
this._action.clampWhenFinished = true;
|
||||
this._action.play();
|
||||
// Make sure the first frame is displayed.
|
||||
this._animationMixer.update(0);
|
||||
}
|
||||
}
|
||||
|
||||
export const Model3DRuntimeObjectRenderer = Model3DRuntimeObject3DRenderer;
|
||||
|
@@ -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)
|
||||
|
@@ -1,27 +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(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()
|
||||
|
@@ -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()
|
||||
|
||||
|
@@ -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)
|
||||
|
@@ -46,7 +46,7 @@ module.exports = {
|
||||
_(
|
||||
'Load a dialogue data object - Yarn json format, stored in a scene variable. Use this command to load all the Dialogue data at the beginning of the game.'
|
||||
),
|
||||
_('Load dialogue data from Scene variable _PARAM1_'),
|
||||
_('Load dialogue data from Scene variable _PARAM0_'),
|
||||
'',
|
||||
'JsPlatform/Extensions/yarn32.png',
|
||||
'JsPlatform/Extensions/yarn32.png'
|
||||
|
@@ -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)
|
||||
|
@@ -41,7 +41,7 @@ namespace gdjs {
|
||||
/**
|
||||
* The current authentication status.
|
||||
*/
|
||||
export let authentified = false;
|
||||
export let authenticated = false;
|
||||
|
||||
/**
|
||||
* The logged-in users data.
|
||||
@@ -345,10 +345,13 @@ namespace gdjs {
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns true if the user is currently authentified.
|
||||
* @see authentified
|
||||
* Returns true if the user is currently authenticated.
|
||||
* @see authenticated
|
||||
*/
|
||||
export const isAuthentified = (): boolean => authentified;
|
||||
export const isAuthenticated = (): boolean => authenticated;
|
||||
|
||||
/** @deprecated Use isAuthenticated instead. */
|
||||
export const isAuthentified = isAuthenticated;
|
||||
|
||||
/**
|
||||
* Signs the user in with basic email-password authentication.
|
||||
@@ -442,14 +445,14 @@ namespace gdjs {
|
||||
firebaseTools.onAppCreated.push(() => {
|
||||
firebase.auth().onAuthStateChanged((user) => {
|
||||
if (user) {
|
||||
authentified = true;
|
||||
authenticated = true;
|
||||
currentUser = user;
|
||||
user.getIdToken().then(
|
||||
// Prefetch the token
|
||||
(token) => (_token = token)
|
||||
);
|
||||
} else {
|
||||
authentified = false;
|
||||
authenticated = false;
|
||||
currentUser = null;
|
||||
}
|
||||
});
|
||||
|
@@ -14,7 +14,7 @@ namespace gdjs {
|
||||
/**
|
||||
* Uploads a file as string to the firebase storage bucket.
|
||||
* @param file - The entire file as string.
|
||||
* @param onlinePath - The path under wich the file will be accessible on the bucket.
|
||||
* @param onlinePath - The path under which the file will be accessible on the bucket.
|
||||
* @param [type] - The type/format of the string to upload.
|
||||
* @param [callbackStateVariable] - The variable where to store if the operation was successful.
|
||||
* @param [callbackValueVariable] - The variable where to store the result (url to the file).
|
||||
|
@@ -395,7 +395,7 @@ module.exports = {
|
||||
.addIncludeFile('Extensions/Firebase/A_firebasejs/B_firebase-auth.js')
|
||||
.addIncludeFile('Extensions/Firebase/B_firebasetools/C_firebasetools.js')
|
||||
.addIncludeFile('Extensions/Firebase/B_firebasetools/D_authtools.js')
|
||||
.setFunctionName('gdjs.evtTools.firebaseTools.auth.isAuthentified');
|
||||
.setFunctionName('gdjs.evtTools.firebaseTools.auth.isAuthenticated');
|
||||
|
||||
extension
|
||||
.addStrExpression(
|
||||
|
@@ -533,7 +533,7 @@ describeIfOnline('Firebase extension end-to-end tests', function () {
|
||||
const password2 = `myNewPass${Math.random().toString(16)}${Date.now()}!`;
|
||||
|
||||
const expectToNotLogin = async (password) => {
|
||||
if (gdjs.evtTools.firebaseTools.auth.isAuthentified())
|
||||
if (gdjs.evtTools.firebaseTools.auth.isAuthenticated())
|
||||
await firebase.auth().signOut();
|
||||
|
||||
let errors = false;
|
||||
@@ -553,11 +553,11 @@ describeIfOnline('Firebase extension end-to-end tests', function () {
|
||||
if (!errors)
|
||||
throw new Error('Expected wrong credentials to prevent login');
|
||||
|
||||
expect(gdjs.evtTools.firebaseTools.auth.isAuthentified()).to.not.be.ok();
|
||||
expect(gdjs.evtTools.firebaseTools.auth.isAuthenticated()).to.not.be.ok();
|
||||
};
|
||||
|
||||
const expectToLogin = async (password) => {
|
||||
if (gdjs.evtTools.firebaseTools.auth.isAuthentified())
|
||||
if (gdjs.evtTools.firebaseTools.auth.isAuthenticated())
|
||||
await firebase.auth().signOut();
|
||||
|
||||
await promisifyCallbackVariables((callback) =>
|
||||
@@ -568,13 +568,13 @@ describeIfOnline('Firebase extension end-to-end tests', function () {
|
||||
)
|
||||
);
|
||||
|
||||
expect(gdjs.evtTools.firebaseTools.auth.isAuthentified()).to.be.ok();
|
||||
expect(gdjs.evtTools.firebaseTools.auth.isAuthenticated()).to.be.ok();
|
||||
};
|
||||
|
||||
before(async () => firebase.auth().signOut());
|
||||
|
||||
it('let users create accounts', async () => {
|
||||
expect(gdjs.evtTools.firebaseTools.auth.isAuthentified()).to.not.be.ok();
|
||||
expect(gdjs.evtTools.firebaseTools.auth.isAuthenticated()).to.not.be.ok();
|
||||
|
||||
await promisifyCallbackVariables((callback) =>
|
||||
gdjs.evtTools.firebaseTools.auth.createAccountWithEmail(
|
||||
@@ -584,13 +584,13 @@ describeIfOnline('Firebase extension end-to-end tests', function () {
|
||||
)
|
||||
);
|
||||
|
||||
expect(gdjs.evtTools.firebaseTools.auth.isAuthentified()).to.be.ok();
|
||||
expect(gdjs.evtTools.firebaseTools.auth.isAuthenticated()).to.be.ok();
|
||||
});
|
||||
|
||||
it('let users log out', async () => {
|
||||
expect(gdjs.evtTools.firebaseTools.auth.isAuthentified()).to.be.ok();
|
||||
expect(gdjs.evtTools.firebaseTools.auth.isAuthenticated()).to.be.ok();
|
||||
await firebase.auth().signOut();
|
||||
expect(gdjs.evtTools.firebaseTools.auth.isAuthentified()).to.not.be.ok();
|
||||
expect(gdjs.evtTools.firebaseTools.auth.isAuthenticated()).to.not.be.ok();
|
||||
});
|
||||
|
||||
it('prevents logging in with invalid credentials', async () =>
|
||||
|
@@ -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)
|
||||
|
@@ -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");
|
||||
|
@@ -18,6 +18,7 @@ export type ObjectsRenderingService = {
|
||||
gd: libGDevelop,
|
||||
PIXI: any,
|
||||
THREE: any,
|
||||
THREE_ADDONS: {SkeletonUtils: any},
|
||||
RenderedInstance: any,
|
||||
Rendered3DInstance: any,
|
||||
registerInstanceRenderer: (objectType: string, renderer: any) => void,
|
||||
|
@@ -290,74 +290,31 @@ module.exports = {
|
||||
.getValue()
|
||||
);
|
||||
if (this._radius <= 0) this._radius = 1;
|
||||
const colorHex = objectsRenderingService.rgbOrHexToHexNumber(
|
||||
const color = objectsRenderingService.rgbOrHexToHexNumber(
|
||||
this._associatedObjectConfiguration
|
||||
.getProperties(this.project)
|
||||
.get('color')
|
||||
.getValue()
|
||||
);
|
||||
this._color = [
|
||||
((colorHex >> 16) & 0xff) / 255,
|
||||
((colorHex >> 8) & 0xff) / 255,
|
||||
(colorHex & 0xff) / 255,
|
||||
];
|
||||
|
||||
const geometry = new PIXI.Geometry();
|
||||
const shader = PIXI.Shader.from(
|
||||
`
|
||||
precision mediump float;
|
||||
attribute vec2 aVertexPosition;
|
||||
// The icon in the middle.
|
||||
const lightIconSprite = new PIXI.Sprite(PIXI.Texture.from('CppPlatform/Extensions/lightIcon32.png'));
|
||||
lightIconSprite.anchor.x = 0.5;
|
||||
lightIconSprite.anchor.y = 0.5;
|
||||
|
||||
uniform mat3 translationMatrix;
|
||||
uniform mat3 projectionMatrix;
|
||||
varying vec2 vPos;
|
||||
|
||||
void main() {
|
||||
vPos = aVertexPosition;
|
||||
gl_Position = vec4((projectionMatrix * translationMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);
|
||||
}`,
|
||||
`
|
||||
precision mediump float;
|
||||
uniform vec2 center;
|
||||
uniform float radius;
|
||||
uniform vec3 color;
|
||||
uniform mat3 translationMatrix;
|
||||
uniform mat3 projectionMatrix;
|
||||
|
||||
varying vec2 vPos;
|
||||
|
||||
void main() {
|
||||
float l = length(vPos - center);
|
||||
float intensity = 0.0;
|
||||
if(l < radius)
|
||||
intensity = clamp((radius - l)*(radius - l)/(radius*radius), 0.0, 1.0);
|
||||
gl_FragColor = vec4(color*intensity, 1.0);
|
||||
}
|
||||
`,
|
||||
{
|
||||
center: [this._instance.getX(), this._instance.getY()],
|
||||
radius: this._radius,
|
||||
color: this._color,
|
||||
}
|
||||
// The circle to show the radius of the light.
|
||||
const radiusBorderWidth = 2;
|
||||
const radiusGraphics = new PIXI.Graphics();
|
||||
radiusGraphics.lineStyle(
|
||||
radiusBorderWidth,
|
||||
color,
|
||||
0.8
|
||||
);
|
||||
radiusGraphics.drawCircle(0, 0, Math.max(1, this._radius - radiusBorderWidth));
|
||||
|
||||
this._vertexBuffer = new Float32Array([
|
||||
this._instance.getX() - this._radius,
|
||||
this._instance.getY() + this._radius,
|
||||
this._instance.getX() + this._radius,
|
||||
this._instance.getY() + this._radius,
|
||||
this._instance.getX() + this._radius,
|
||||
this._instance.getY() - this._radius,
|
||||
this._instance.getX() - this._radius,
|
||||
this._instance.getY() - this._radius,
|
||||
]);
|
||||
|
||||
geometry
|
||||
.addAttribute('aVertexPosition', this._vertexBuffer, 2)
|
||||
.addIndex([0, 1, 2, 2, 3, 0]);
|
||||
|
||||
this._pixiObject = new PIXI.Mesh(geometry, shader);
|
||||
this._pixiObject.blendMode = PIXI.BLEND_MODES.ADD;
|
||||
this._pixiObject = new PIXI.Container();
|
||||
this._pixiObject.addChild(lightIconSprite);
|
||||
this._pixiObject.addChild(radiusGraphics);
|
||||
this._pixiContainer.addChild(this._pixiObject);
|
||||
this.update();
|
||||
}
|
||||
@@ -380,37 +337,22 @@ module.exports = {
|
||||
* This is called to update the PIXI object on the scene editor
|
||||
*/
|
||||
RenderedLightObjectInstance.prototype.update = function () {
|
||||
this._pixiObject.shader.uniforms.center = new Float32Array([
|
||||
this._instance.getX(),
|
||||
this._instance.getY(),
|
||||
]);
|
||||
|
||||
this._vertexBuffer[0] = this._instance.getX() - this._radius;
|
||||
this._vertexBuffer[1] = this._instance.getY() + this._radius;
|
||||
this._vertexBuffer[2] = this._instance.getX() + this._radius;
|
||||
this._vertexBuffer[3] = this._instance.getY() + this._radius;
|
||||
this._vertexBuffer[4] = this._instance.getX() + this._radius;
|
||||
this._vertexBuffer[5] = this._instance.getY() - this._radius;
|
||||
this._vertexBuffer[6] = this._instance.getX() - this._radius;
|
||||
this._vertexBuffer[7] = this._instance.getY() - this._radius;
|
||||
|
||||
this._pixiObject.geometry
|
||||
.getBuffer('aVertexPosition')
|
||||
.update(this._vertexBuffer);
|
||||
this._pixiObject.position.x = this._instance.getX();
|
||||
this._pixiObject.position.y = this._instance.getY();
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the width of the instance, when it's not resized.
|
||||
*/
|
||||
RenderedLightObjectInstance.prototype.getDefaultWidth = function () {
|
||||
return this._pixiObject.width;
|
||||
return this._radius * 2;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the height of the instance, when it's not resized.
|
||||
*/
|
||||
RenderedLightObjectInstance.prototype.getDefaultHeight = function () {
|
||||
return this._pixiObject.height;
|
||||
return this._radius * 2;
|
||||
};
|
||||
|
||||
RenderedLightObjectInstance.prototype.getOriginX = function () {
|
||||
|
@@ -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)
|
||||
|
@@ -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");
|
||||
|
||||
|
@@ -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)
|
||||
|
@@ -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)
|
||||
|
@@ -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)
|
||||
|
@@ -758,7 +758,7 @@ module.exports = {
|
||||
|
||||
aut
|
||||
.addAction(
|
||||
'SetSleepingaAllowed',
|
||||
'SetSleepingAllowed',
|
||||
_('Sleeping allowed'),
|
||||
_(
|
||||
'Allow or not an object to sleep. If enabled the object will be able to sleep, improving performance for non-currently-moving objects.'
|
||||
@@ -774,6 +774,11 @@ module.exports = {
|
||||
.setDefaultValue('true')
|
||||
.getCodeExtraInformation()
|
||||
.setFunctionName('setSleepingAllowed');
|
||||
|
||||
// Deprecated action (fixed typo):
|
||||
aut
|
||||
.addDuplicatedAction("SetSleepingaAllowed", "SetSleepingAllowed")
|
||||
.setHidden();
|
||||
|
||||
aut
|
||||
.addCondition(
|
||||
|
@@ -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)
|
||||
|
@@ -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)
|
||||
|
@@ -140,7 +140,7 @@ namespace gdjs {
|
||||
} else if (behaviorData.platformType === 'Jumpthru') {
|
||||
this._platformType = PlatformRuntimeBehavior.JUMPTHRU;
|
||||
} else {
|
||||
this._platformType = PlatformRuntimeBehavior.NORMALPLAFTORM;
|
||||
this._platformType = PlatformRuntimeBehavior.NORMALPLATFORM;
|
||||
}
|
||||
this._canBeGrabbed = behaviorData.canBeGrabbed || false;
|
||||
this._yGrabOffset = behaviorData.yGrabOffset || 0;
|
||||
@@ -232,7 +232,7 @@ namespace gdjs {
|
||||
} else if (platformType === 'Jumpthru') {
|
||||
this._platformType = PlatformRuntimeBehavior.JUMPTHRU;
|
||||
} else {
|
||||
this._platformType = PlatformRuntimeBehavior.NORMALPLAFTORM;
|
||||
this._platformType = PlatformRuntimeBehavior.NORMALPLATFORM;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,7 +248,9 @@ namespace gdjs {
|
||||
return this._yGrabOffset;
|
||||
}
|
||||
|
||||
static NORMALPLAFTORM = 0;
|
||||
static NORMALPLATFORM = 0;
|
||||
/** @deprecated Use NORMALPLATFORM instead. */
|
||||
static NORMALPLAFTORM = PlatformRuntimeBehavior.NORMALPLATFORM;
|
||||
static JUMPTHRU = 1;
|
||||
static LADDER = 2;
|
||||
|
||||
|
@@ -598,8 +598,8 @@ namespace gdjs {
|
||||
break;
|
||||
}
|
||||
case 'connectionId': {
|
||||
const messagegeData = messageContent.data;
|
||||
const connectionId = messagegeData.connectionId;
|
||||
const messageData = messageContent.data;
|
||||
const connectionId = messageData.connectionId;
|
||||
if (!connectionId) {
|
||||
logger.error('No connectionId received');
|
||||
return;
|
||||
|
@@ -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)
|
||||
|
@@ -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)
|
||||
|
@@ -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");
|
||||
|
@@ -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)
|
||||
|
@@ -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");
|
||||
|
||||
|
@@ -5,47 +5,7 @@
|
||||
namespace gdjs {
|
||||
export namespace evtTools {
|
||||
export namespace systemInfo {
|
||||
let cachedIsMobile: boolean | null = null;
|
||||
let cachedHasTouchScreen: boolean | null = null;
|
||||
const checkIsMobile = (): boolean => {
|
||||
if (typeof cc !== 'undefined' && cc.sys) {
|
||||
return cc.sys.isMobile;
|
||||
}
|
||||
// @ts-expect-error ts-migrate(2304) FIXME: Cannot find name 'Cocoon'.
|
||||
else if (typeof Cocoon !== 'undefined' && Cocoon.App) {
|
||||
return true;
|
||||
} else if (typeof window !== 'undefined' && (window as any).cordova) {
|
||||
return true;
|
||||
} else if (typeof window !== 'undefined') {
|
||||
// Try to detect mobile device browsers.
|
||||
if (
|
||||
/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|ipad|iris|kindle|Android|Silk|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(
|
||||
navigator.userAgent
|
||||
) ||
|
||||
/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(
|
||||
navigator.userAgent.substr(0, 4)
|
||||
)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Try to detect iOS
|
||||
if (/iPad|iPhone|iPod/.test(navigator.platform)) {
|
||||
return true;
|
||||
} else {
|
||||
if (/MacIntel/.test(navigator.platform)) {
|
||||
// Work around for recent iPads that are "desktop-class browsing".
|
||||
// We can still detect them using their touchscreen, but this is a hack.
|
||||
// If mac laptops start to support touchscreens, this won't work anymore. Hence it's better
|
||||
// to test for the presence of a touchscreen if needed rather than checking if the device
|
||||
// is "mobile".
|
||||
return !!navigator.maxTouchPoints && navigator.maxTouchPoints > 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if the game runs on a mobile device (iPhone, iPad, Android).
|
||||
@@ -54,10 +14,7 @@ namespace gdjs {
|
||||
* prefer to check if the device has touchscreen support.
|
||||
*/
|
||||
export const isMobile = (): boolean => {
|
||||
if (cachedIsMobile !== null) {
|
||||
return cachedIsMobile;
|
||||
}
|
||||
return (cachedIsMobile = checkIsMobile());
|
||||
return gdjs.evtTools.common.isMobile();
|
||||
};
|
||||
|
||||
/**
|
||||
|
@@ -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)
|
||||
|
@@ -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)
|
||||
|
@@ -387,7 +387,7 @@ const defineTileMap = function (
|
||||
)
|
||||
.addParameter('object', _('Tile map'), 'TileMap', false)
|
||||
.useStandardParameters('number', gd.ParameterOptions.makeNewOptions())
|
||||
.setFunctionName('getLevelndex');
|
||||
.setFunctionName('getLevelIndex');
|
||||
|
||||
object
|
||||
.addCondition(
|
||||
@@ -1531,7 +1531,7 @@ module.exports = {
|
||||
this._loadTiledMapWithCallback.bind(this),
|
||||
tilemapJsonFile,
|
||||
tilesetJsonFile,
|
||||
0, // leveIndex
|
||||
0, // levelIndex
|
||||
pako,
|
||||
(tileMap) => {
|
||||
if (!tileMap) {
|
||||
|
File diff suppressed because one or more lines are too long
@@ -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)
|
||||
|
@@ -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)
|
||||
|
@@ -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()
|
||||
|
@@ -684,15 +684,15 @@ gd::String EventsCodeGenerator::GenerateFreeCondition(
|
||||
bool conditionInverted,
|
||||
gd::EventsCodeGenerationContext& context) {
|
||||
// Generate call
|
||||
gd::String predicat;
|
||||
gd::String predicate;
|
||||
if (instrInfos.codeExtraInformation.type == "number" ||
|
||||
instrInfos.codeExtraInformation.type == "string") {
|
||||
predicat = GenerateRelationalOperatorCall(
|
||||
predicate = GenerateRelationalOperatorCall(
|
||||
instrInfos,
|
||||
arguments,
|
||||
instrInfos.codeExtraInformation.functionCallName);
|
||||
} else {
|
||||
predicat = instrInfos.codeExtraInformation.functionCallName + "(" +
|
||||
predicate = instrInfos.codeExtraInformation.functionCallName + "(" +
|
||||
GenerateArgumentsList(arguments) + ")";
|
||||
}
|
||||
|
||||
@@ -705,11 +705,11 @@ gd::String EventsCodeGenerator::GenerateFreeCondition(
|
||||
conditionAlreadyTakeCareOfInversion = true;
|
||||
}
|
||||
if (!conditionAlreadyTakeCareOfInversion && conditionInverted)
|
||||
predicat = GenerateNegatedPredicat(predicat);
|
||||
predicate = GenerateNegatedPredicate(predicate);
|
||||
|
||||
// Generate condition code
|
||||
return GenerateBooleanFullName(returnBoolean, context) +
|
||||
" = " + predicat + ";\n";
|
||||
" = " + predicate + ";\n";
|
||||
}
|
||||
|
||||
gd::String EventsCodeGenerator::GenerateObjectCondition(
|
||||
@@ -728,22 +728,22 @@ gd::String EventsCodeGenerator::GenerateObjectCondition(
|
||||
instrInfos.codeExtraInformation.functionCallName;
|
||||
|
||||
// Create call
|
||||
gd::String predicat;
|
||||
gd::String predicate;
|
||||
if ((instrInfos.codeExtraInformation.type == "number" ||
|
||||
instrInfos.codeExtraInformation.type == "string")) {
|
||||
predicat = GenerateRelationalOperatorCall(
|
||||
predicate = GenerateRelationalOperatorCall(
|
||||
instrInfos, arguments, objectFunctionCallNamePart, 1);
|
||||
} else {
|
||||
predicat = objectFunctionCallNamePart + "(" +
|
||||
predicate = objectFunctionCallNamePart + "(" +
|
||||
GenerateArgumentsList(arguments, 1) + ")";
|
||||
}
|
||||
if (conditionInverted) predicat = GenerateNegatedPredicat(predicat);
|
||||
if (conditionInverted) predicate = GenerateNegatedPredicate(predicate);
|
||||
|
||||
// Generate whole condition code
|
||||
conditionCode +=
|
||||
"for (var i = 0, k = 0, l = " + GetObjectListName(objectName, context) +
|
||||
".length;i<l;++i) {\n";
|
||||
conditionCode += " if ( " + predicat + " ) {\n";
|
||||
conditionCode += " if ( " + predicate + " ) {\n";
|
||||
conditionCode += " " +
|
||||
GenerateBooleanFullName(returnBoolean, context) +
|
||||
" = true;\n";
|
||||
@@ -775,16 +775,16 @@ gd::String EventsCodeGenerator::GenerateBehaviorCondition(
|
||||
instrInfos.codeExtraInformation.functionCallName;
|
||||
|
||||
// Create call
|
||||
gd::String predicat;
|
||||
gd::String predicate;
|
||||
if ((instrInfos.codeExtraInformation.type == "number" ||
|
||||
instrInfos.codeExtraInformation.type == "string")) {
|
||||
predicat = GenerateRelationalOperatorCall(
|
||||
predicate = GenerateRelationalOperatorCall(
|
||||
instrInfos, arguments, objectFunctionCallNamePart, 2);
|
||||
} else {
|
||||
predicat = objectFunctionCallNamePart + "(" +
|
||||
predicate = objectFunctionCallNamePart + "(" +
|
||||
GenerateArgumentsList(arguments, 2) + ")";
|
||||
}
|
||||
if (conditionInverted) predicat = GenerateNegatedPredicat(predicat);
|
||||
if (conditionInverted) predicate = GenerateNegatedPredicate(predicate);
|
||||
|
||||
// Verify that object has behavior.
|
||||
vector<gd::String> behaviors = gd::GetBehaviorsOfObject(
|
||||
@@ -798,7 +798,7 @@ gd::String EventsCodeGenerator::GenerateBehaviorCondition(
|
||||
conditionCode +=
|
||||
"for (var i = 0, k = 0, l = " + GetObjectListName(objectName, context) +
|
||||
".length;i<l;++i) {\n";
|
||||
conditionCode += " if ( " + predicat + " ) {\n";
|
||||
conditionCode += " if ( " + predicate + " ) {\n";
|
||||
conditionCode += " " +
|
||||
GenerateBooleanFullName(returnBoolean, context) +
|
||||
" = true;\n";
|
||||
|
@@ -319,8 +319,8 @@ class EventsCodeGenerator : public gd::EventsCodeGenerator {
|
||||
const gd::String& type,
|
||||
gd::EventsCodeGenerationContext& context);
|
||||
|
||||
virtual gd::String GenerateNegatedPredicat(const gd::String& predicat) const {
|
||||
return "!(" + predicat + ")";
|
||||
virtual gd::String GenerateNegatedPredicate(const gd::String& predicate) const {
|
||||
return "!(" + predicate + ")";
|
||||
};
|
||||
|
||||
virtual gd::String GenerateObjectsDeclarationCode(
|
||||
|
1486
GDJS/GDJS/Events/CodeGeneration/MetadataDeclarationHelper.cpp
Normal file
1486
GDJS/GDJS/Events/CodeGeneration/MetadataDeclarationHelper.cpp
Normal file
File diff suppressed because it is too large
Load Diff
324
GDJS/GDJS/Events/CodeGeneration/MetadataDeclarationHelper.h
Normal file
324
GDJS/GDJS/Events/CodeGeneration/MetadataDeclarationHelper.h
Normal 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 ¶meter);
|
||||
|
||||
/**
|
||||
* 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
|
@@ -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) {
|
||||
|
@@ -138,12 +138,10 @@ BaseObjectExtension::BaseObjectExtension() {
|
||||
objectActions["SeparateFromObjects"]
|
||||
.SetFunctionName("separateFromObjectsList")
|
||||
.SetIncludeFile("runtimeobject.js");
|
||||
objectActions["Ecarter"]
|
||||
.codeExtraInformation // Deprecated
|
||||
objectActions["Ecarter"] // Deprecated
|
||||
.SetFunctionName("separateObjectsWithoutForces")
|
||||
.SetIncludeFile("runtimeobject.js");
|
||||
objectActions["Rebondir"]
|
||||
.codeExtraInformation // Deprecated
|
||||
objectActions["Rebondir"] // Deprecated
|
||||
.SetFunctionName("separateObjectsWithForces")
|
||||
.SetIncludeFile("runtimeobject.js");
|
||||
objectConditions["BehaviorActivated"]
|
||||
@@ -354,7 +352,7 @@ BaseObjectExtension::BaseObjectExtension() {
|
||||
.SetFunctionName("getVariableChildCount")
|
||||
.SetIncludeFile("runtimeobject.js");
|
||||
|
||||
GetAllActions()["MoveObjects"].codeExtraInformation.SetCustomCodeGenerator(
|
||||
GetAllActions()["MoveObjects"].SetCustomCodeGenerator(
|
||||
[](gd::Instruction &,
|
||||
gd::EventsCodeGenerator &,
|
||||
gd::EventsCodeGenerationContext &) {
|
||||
@@ -365,7 +363,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 +395,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 +420,7 @@ BaseObjectExtension::BaseObjectExtension() {
|
||||
return outputCode;
|
||||
});
|
||||
|
||||
objectActions["SetCenter"].codeExtraInformation.SetCustomCodeGenerator(
|
||||
objectActions["SetCenter"].SetCustomCodeGenerator(
|
||||
[&](gd::Instruction &instruction,
|
||||
gd::EventsCodeGenerator &codeGenerator,
|
||||
gd::EventsCodeGenerationContext &context) -> gd::String {
|
||||
|
@@ -46,7 +46,7 @@ CommonInstructionsExtension::CommonInstructionsExtension() {
|
||||
GetAllConditions()["BuiltinCommonInstructions::Always"].SetFunctionName(
|
||||
"gdjs.evtTools.common.logicalNegation");
|
||||
|
||||
GetAllConditions()["Egal"].codeExtraInformation.SetCustomCodeGenerator(
|
||||
GetAllConditions()["Egal"].SetCustomCodeGenerator(
|
||||
[](gd::Instruction& instruction,
|
||||
gd::EventsCodeGenerator& codeGenerator,
|
||||
gd::EventsCodeGenerationContext& context) {
|
||||
@@ -76,7 +76,7 @@ CommonInstructionsExtension::CommonInstructionsExtension() {
|
||||
GetAllConditions()["BuiltinCommonInstructions::CompareNumbers"]
|
||||
.codeExtraInformation = GetAllConditions()["Egal"].codeExtraInformation;
|
||||
|
||||
GetAllConditions()["StrEqual"].codeExtraInformation.SetCustomCodeGenerator(
|
||||
GetAllConditions()["StrEqual"].SetCustomCodeGenerator(
|
||||
[](gd::Instruction& instruction,
|
||||
gd::EventsCodeGenerator& codeGenerator,
|
||||
gd::EventsCodeGenerationContext& context) {
|
||||
@@ -133,7 +133,7 @@ CommonInstructionsExtension::CommonInstructionsExtension() {
|
||||
|
||||
gd::String conditionsCode = codeGenerator.GenerateConditionsListCode(
|
||||
event.GetConditions(), context);
|
||||
gd::String ifPredicat =
|
||||
gd::String ifPredicate =
|
||||
event.GetConditions().empty()
|
||||
? ""
|
||||
: codeGenerator.GenerateBooleanFullName(
|
||||
@@ -156,7 +156,7 @@ CommonInstructionsExtension::CommonInstructionsExtension() {
|
||||
|
||||
gd::String outputCode;
|
||||
outputCode += conditionsCode;
|
||||
if (!ifPredicat.empty()) outputCode += "if (" + ifPredicat + ") ";
|
||||
if (!ifPredicate.empty()) outputCode += "if (" + ifPredicate + ") ";
|
||||
outputCode += "{\n";
|
||||
outputCode += actionsDeclarationsCode;
|
||||
outputCode += actionsCode;
|
||||
@@ -176,7 +176,7 @@ CommonInstructionsExtension::CommonInstructionsExtension() {
|
||||
});
|
||||
|
||||
GetAllConditions()["BuiltinCommonInstructions::Or"]
|
||||
.codeExtraInformation.SetCustomCodeGenerator(
|
||||
.SetCustomCodeGenerator(
|
||||
[](gd::Instruction& instruction,
|
||||
gd::EventsCodeGenerator& codeGenerator,
|
||||
gd::EventsCodeGenerationContext& parentContext) {
|
||||
@@ -307,7 +307,7 @@ CommonInstructionsExtension::CommonInstructionsExtension() {
|
||||
});
|
||||
|
||||
GetAllConditions()["BuiltinCommonInstructions::And"]
|
||||
.codeExtraInformation.SetCustomCodeGenerator(
|
||||
.SetCustomCodeGenerator(
|
||||
[](gd::Instruction& instruction,
|
||||
gd::EventsCodeGenerator& codeGenerator,
|
||||
gd::EventsCodeGenerationContext& parentContext) {
|
||||
@@ -327,7 +327,7 @@ CommonInstructionsExtension::CommonInstructionsExtension() {
|
||||
});
|
||||
|
||||
GetAllConditions()["BuiltinCommonInstructions::Not"]
|
||||
.codeExtraInformation.SetCustomCodeGenerator(
|
||||
.SetCustomCodeGenerator(
|
||||
[](gd::Instruction &instruction,
|
||||
gd::EventsCodeGenerator &codeGenerator,
|
||||
gd::EventsCodeGenerationContext &parentContext) {
|
||||
@@ -348,7 +348,7 @@ CommonInstructionsExtension::CommonInstructionsExtension() {
|
||||
});
|
||||
|
||||
GetAllConditions()["BuiltinCommonInstructions::Once"]
|
||||
.codeExtraInformation.SetCustomCodeGenerator(
|
||||
.SetCustomCodeGenerator(
|
||||
[](gd::Instruction& instruction,
|
||||
gd::EventsCodeGenerator& codeGenerator,
|
||||
gd::EventsCodeGenerationContext& context) {
|
||||
@@ -391,18 +391,18 @@ CommonInstructionsExtension::CommonInstructionsExtension() {
|
||||
gd::String whileConditionsStr =
|
||||
codeGenerator.GenerateConditionsListCode(event.GetWhileConditions(),
|
||||
context);
|
||||
gd::String whileIfPredicat = "true";
|
||||
gd::String whileIfPredicate = "true";
|
||||
if (!event.GetWhileConditions().empty())
|
||||
whileIfPredicat =
|
||||
whileIfPredicate =
|
||||
codeGenerator.GenerateBooleanFullName("isConditionTrue", context);
|
||||
|
||||
gd::String conditionsCode = codeGenerator.GenerateConditionsListCode(
|
||||
event.GetConditions(), context);
|
||||
gd::String actionsCode =
|
||||
codeGenerator.GenerateActionsListCode(event.GetActions(), context);
|
||||
gd::String ifPredicat = "true";
|
||||
gd::String ifPredicate = "true";
|
||||
if (!event.GetConditions().empty())
|
||||
ifPredicat =
|
||||
ifPredicate =
|
||||
codeGenerator.GenerateBooleanFullName("isConditionTrue", context);
|
||||
|
||||
// Write final code
|
||||
@@ -412,9 +412,9 @@ CommonInstructionsExtension::CommonInstructionsExtension() {
|
||||
outputCode += "do {\n";
|
||||
outputCode += codeGenerator.GenerateObjectsDeclarationCode(context);
|
||||
outputCode += whileConditionsStr;
|
||||
outputCode += "if (" + whileIfPredicat + ") {\n";
|
||||
outputCode += "if (" + whileIfPredicate + ") {\n";
|
||||
outputCode += conditionsCode;
|
||||
outputCode += "if (" + ifPredicat + ") {\n";
|
||||
outputCode += "if (" + ifPredicate + ") {\n";
|
||||
outputCode += actionsCode;
|
||||
outputCode += "\n{ //Subevents: \n";
|
||||
// TODO: check (and heavily test) if sub events should be generated before
|
||||
@@ -448,7 +448,7 @@ CommonInstructionsExtension::CommonInstructionsExtension() {
|
||||
event.GetConditions(), context);
|
||||
gd::String actionsCode =
|
||||
codeGenerator.GenerateActionsListCode(event.GetActions(), context);
|
||||
gd::String ifPredicat = event.GetConditions().empty()
|
||||
gd::String ifPredicate = event.GetConditions().empty()
|
||||
? "true"
|
||||
: codeGenerator.GenerateBooleanFullName(
|
||||
"isConditionTrue", context);
|
||||
@@ -524,7 +524,7 @@ CommonInstructionsExtension::CommonInstructionsExtension() {
|
||||
// Now do the rest of standard event code generation
|
||||
outputCode += objectDeclaration;
|
||||
outputCode += conditionsCode;
|
||||
outputCode += "if (" + ifPredicat + ")\n";
|
||||
outputCode += "if (" + ifPredicate + ")\n";
|
||||
outputCode += "{\n";
|
||||
outputCode += actionsCode;
|
||||
if (event.HasSubEvents()) {
|
||||
@@ -613,9 +613,9 @@ CommonInstructionsExtension::CommonInstructionsExtension() {
|
||||
event.GetConditions(), context);
|
||||
gd::String actionsCode =
|
||||
codeGenerator.GenerateActionsListCode(event.GetActions(), context);
|
||||
gd::String ifPredicat = "true";
|
||||
gd::String ifPredicate = "true";
|
||||
if (!event.GetConditions().empty())
|
||||
ifPredicat =
|
||||
ifPredicate =
|
||||
codeGenerator.GenerateBooleanFullName("isConditionTrue", context);
|
||||
|
||||
// Prepare object declaration and sub events
|
||||
@@ -634,7 +634,7 @@ CommonInstructionsExtension::CommonInstructionsExtension() {
|
||||
" < " + repeatCountVar + ";++" + repeatIndexVar + ") {\n";
|
||||
outputCode += objectDeclaration;
|
||||
outputCode += conditionsCode;
|
||||
outputCode += "if (" + ifPredicat + ")\n";
|
||||
outputCode += "if (" + ifPredicate + ")\n";
|
||||
outputCode += "{\n";
|
||||
outputCode += actionsCode;
|
||||
if (event.HasSubEvents()) {
|
||||
@@ -677,9 +677,9 @@ CommonInstructionsExtension::CommonInstructionsExtension() {
|
||||
event.GetConditions(), context);
|
||||
gd::String actionsCode =
|
||||
codeGenerator.GenerateActionsListCode(event.GetActions(), context);
|
||||
gd::String ifPredicat = "true";
|
||||
gd::String ifPredicate = "true";
|
||||
if (!event.GetConditions().empty())
|
||||
ifPredicat =
|
||||
ifPredicate =
|
||||
codeGenerator.GenerateBooleanFullName("isConditionTrue", context);
|
||||
|
||||
// Prepare object declaration and sub events
|
||||
@@ -787,7 +787,7 @@ CommonInstructionsExtension::CommonInstructionsExtension() {
|
||||
}
|
||||
|
||||
outputCode += conditionsCode;
|
||||
outputCode += "if (" + ifPredicat + ") {\n";
|
||||
outputCode += "if (" + ifPredicate + ") {\n";
|
||||
outputCode += actionsCode;
|
||||
if (event.HasSubEvents()) {
|
||||
outputCode += "\n{ //Subevents: \n";
|
||||
|
@@ -118,7 +118,7 @@ VariablesExtension::VariablesExtension() {
|
||||
GetAllActions()["GlobalVariableRemoveAt"].SetFunctionName(
|
||||
"gdjs.evtTools.variable.variableRemoveAt");
|
||||
|
||||
GetAllActions()["ModVarScene"].codeExtraInformation.SetCustomCodeGenerator(
|
||||
GetAllActions()["ModVarScene"].SetCustomCodeGenerator(
|
||||
[](gd::Instruction& instruction,
|
||||
gd::EventsCodeGenerator& codeGenerator,
|
||||
gd::EventsCodeGenerationContext& context) {
|
||||
@@ -150,7 +150,7 @@ VariablesExtension::VariablesExtension() {
|
||||
return gd::String("");
|
||||
});
|
||||
|
||||
GetAllActions()["ModVarSceneTxt"].codeExtraInformation.SetCustomCodeGenerator(
|
||||
GetAllActions()["ModVarSceneTxt"].SetCustomCodeGenerator(
|
||||
[](gd::Instruction& instruction,
|
||||
gd::EventsCodeGenerator& codeGenerator,
|
||||
gd::EventsCodeGenerationContext& context) {
|
||||
@@ -176,7 +176,7 @@ VariablesExtension::VariablesExtension() {
|
||||
return gd::String("");
|
||||
});
|
||||
|
||||
GetAllActions()["ModVarGlobal"].codeExtraInformation.SetCustomCodeGenerator(
|
||||
GetAllActions()["ModVarGlobal"].SetCustomCodeGenerator(
|
||||
[](gd::Instruction& instruction,
|
||||
gd::EventsCodeGenerator& codeGenerator,
|
||||
gd::EventsCodeGenerationContext& context) {
|
||||
@@ -209,7 +209,7 @@ VariablesExtension::VariablesExtension() {
|
||||
});
|
||||
|
||||
GetAllActions()["ModVarGlobalTxt"]
|
||||
.codeExtraInformation.SetCustomCodeGenerator(
|
||||
.SetCustomCodeGenerator(
|
||||
[](gd::Instruction& instruction,
|
||||
gd::EventsCodeGenerator& codeGenerator,
|
||||
gd::EventsCodeGenerationContext& context) {
|
||||
|
@@ -686,6 +686,8 @@ void ExporterHelper::AddLibsInclude(bool pixiRenderers,
|
||||
if (pixiInThreeRenderers) {
|
||||
InsertUnique(includesFiles, "pixi-renderers/three.js");
|
||||
InsertUnique(includesFiles, "pixi-renderers/ThreeAddons.js");
|
||||
InsertUnique(includesFiles, "pixi-renderers/draco/gltf/draco_decoder.wasm");
|
||||
InsertUnique(includesFiles, "pixi-renderers/draco/gltf/draco_wasm_wrapper.js");
|
||||
}
|
||||
if (pixiRenderers) {
|
||||
InsertUnique(includesFiles, "pixi-renderers/pixi.js");
|
||||
|
@@ -16,14 +16,16 @@ namespace gdjs {
|
||||
/**
|
||||
* Map associating a resource name to the loaded Three.js model.
|
||||
*/
|
||||
private _loadedThreeModels = new Map<String, THREE.Object3D>();
|
||||
private _loadedThreeModels = new Map<String, THREE_ADDONS.GLTF>();
|
||||
|
||||
_resourcesLoader: RuntimeGameResourcesLoader;
|
||||
_resources: ResourceData[];
|
||||
|
||||
_loader: THREE_ADDONS.GLTFLoader | null = null;
|
||||
_dracoLoader: THREE_ADDONS.DRACOLoader | null = null;
|
||||
|
||||
_invalidModel: THREE.Object3D | null = null;
|
||||
//@ts-ignore Can only be null if THREE is not loaded.
|
||||
_invalidModel: THREE_ADDONS.GLTF;
|
||||
|
||||
/**
|
||||
* @param resources The resources data of the game.
|
||||
@@ -39,13 +41,31 @@ namespace gdjs {
|
||||
if (typeof THREE !== 'undefined') {
|
||||
this._loader = new THREE_ADDONS.GLTFLoader();
|
||||
|
||||
this._dracoLoader = new THREE_ADDONS.DRACOLoader();
|
||||
this._dracoLoader.setDecoderPath('./pixi-renderers/draco/gltf/');
|
||||
this._loader.setDRACOLoader(this._dracoLoader);
|
||||
|
||||
/**
|
||||
* The invalid model is a box with magenta (#ff00ff) faces, to be
|
||||
* easily spotted if rendered on screen.
|
||||
*/
|
||||
const geometry = new THREE.BoxGeometry(1, 1, 1);
|
||||
const material = new THREE.MeshBasicMaterial({ color: '#ff00ff' });
|
||||
this._invalidModel = new THREE.Mesh(geometry, material);
|
||||
const group = new THREE.Group();
|
||||
group.add(
|
||||
new THREE.Mesh(
|
||||
new THREE.BoxGeometry(1, 1, 1),
|
||||
new THREE.MeshBasicMaterial({ color: '#ff00ff' })
|
||||
)
|
||||
);
|
||||
this._invalidModel = {
|
||||
scene: group,
|
||||
animations: [],
|
||||
cameras: [],
|
||||
scenes: [],
|
||||
asset: {},
|
||||
userData: {},
|
||||
//@ts-ignore
|
||||
parser: null,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,9 +109,8 @@ namespace gdjs {
|
||||
);
|
||||
this._loader.load(
|
||||
url,
|
||||
(gltf) => {
|
||||
gltf.scene.rotation.order = 'ZYX';
|
||||
this._loadedThreeModels.set(resource.name, gltf.scene);
|
||||
(gltf: THREE_ADDONS.GLTF) => {
|
||||
this._loadedThreeModels.set(resource.name, gltf);
|
||||
|
||||
loaded++;
|
||||
if (loaded === model3DResources.length) {
|
||||
@@ -123,7 +142,7 @@ namespace gdjs {
|
||||
* @param resourceName The name of the json resource.
|
||||
* @returns a 3D model if it exists.
|
||||
*/
|
||||
getModel(resourceName: string): THREE.Object3D | null {
|
||||
getModel(resourceName: string): THREE_ADDONS.GLTF {
|
||||
return this._loadedThreeModels.get(resourceName) || this._invalidModel;
|
||||
}
|
||||
}
|
||||
|
@@ -257,8 +257,19 @@ namespace gdjs {
|
||||
newObject.persistentUuid = instanceData.persistentUuid || null;
|
||||
}
|
||||
newObject.setPosition(instanceData.x + xPos, instanceData.y + yPos);
|
||||
newObject.setZOrder(instanceData.zOrder);
|
||||
newObject.setAngle(instanceData.angle);
|
||||
if (
|
||||
gdjs.RuntimeObject3D &&
|
||||
newObject instanceof gdjs.RuntimeObject3D
|
||||
) {
|
||||
if (instanceData.z !== undefined) newObject.setZ(instanceData.z);
|
||||
if (instanceData.rotationX !== undefined)
|
||||
newObject.setRotationX(instanceData.rotationX);
|
||||
if (instanceData.rotationY !== undefined)
|
||||
newObject.setRotationY(instanceData.rotationY);
|
||||
}
|
||||
|
||||
newObject.setZOrder(instanceData.zOrder);
|
||||
newObject.setLayer(instanceData.layer);
|
||||
newObject
|
||||
.getVariables()
|
||||
|
@@ -1252,6 +1252,29 @@ namespace gdjs {
|
||||
runtimeObject.setLayer(newInstance.layer);
|
||||
somethingChanged = true;
|
||||
}
|
||||
if (
|
||||
gdjs.RuntimeObject3D &&
|
||||
runtimeObject instanceof gdjs.RuntimeObject3D
|
||||
) {
|
||||
if (oldInstance.z !== newInstance.z && newInstance.z !== undefined) {
|
||||
runtimeObject.setZ(newInstance.z);
|
||||
somethingChanged = true;
|
||||
}
|
||||
if (
|
||||
oldInstance.rotationX !== newInstance.rotationX &&
|
||||
newInstance.rotationX !== undefined
|
||||
) {
|
||||
runtimeObject.setRotationX(newInstance.rotationX);
|
||||
somethingChanged = true;
|
||||
}
|
||||
if (
|
||||
oldInstance.rotationY !== newInstance.rotationY &&
|
||||
newInstance.rotationY !== undefined
|
||||
) {
|
||||
runtimeObject.setRotationY(newInstance.rotationY);
|
||||
somethingChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if size changed
|
||||
let sizeChanged = false;
|
||||
@@ -1283,6 +1306,28 @@ namespace gdjs {
|
||||
sizeChanged = true;
|
||||
}
|
||||
}
|
||||
if (
|
||||
gdjs.RuntimeObject3D &&
|
||||
runtimeObject instanceof gdjs.RuntimeObject3D
|
||||
) {
|
||||
// A custom depth was set or changed
|
||||
if (
|
||||
oldInstance.depth !== newInstance.depth &&
|
||||
newInstance.depth !== undefined
|
||||
) {
|
||||
runtimeObject.setDepth(newInstance.depth);
|
||||
somethingChanged = true;
|
||||
sizeChanged = true;
|
||||
} else if (
|
||||
newInstance.depth === undefined &&
|
||||
oldInstance.depth !== undefined
|
||||
) {
|
||||
// The custom depth was removed. Just flag the depth as changed
|
||||
// and hope the object will handle this in
|
||||
// `extraInitializationFromInitialInstance`.
|
||||
sizeChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Update variables
|
||||
this._hotReloadVariablesContainer(
|
||||
|
@@ -396,6 +396,60 @@ namespace gdjs {
|
||||
)
|
||||
eventsFunctionContext.task.resolve();
|
||||
};
|
||||
|
||||
const checkIsMobile = (): boolean => {
|
||||
if (typeof cc !== 'undefined' && cc.sys) {
|
||||
return cc.sys.isMobile;
|
||||
}
|
||||
// @ts-expect-error ts-migrate(2304) FIXME: Cannot find name 'Cocoon'.
|
||||
else if (typeof Cocoon !== 'undefined' && Cocoon.App) {
|
||||
return true;
|
||||
} else if (typeof window !== 'undefined' && (window as any).cordova) {
|
||||
return true;
|
||||
} else if (typeof window !== 'undefined') {
|
||||
// Try to detect mobile device browsers.
|
||||
if (
|
||||
/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|ipad|iris|kindle|Android|Silk|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(
|
||||
navigator.userAgent
|
||||
) ||
|
||||
/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(
|
||||
navigator.userAgent.substr(0, 4)
|
||||
)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Try to detect iOS
|
||||
if (/iPad|iPhone|iPod/.test(navigator.platform)) {
|
||||
return true;
|
||||
} else {
|
||||
if (/MacIntel/.test(navigator.platform)) {
|
||||
// Work around for recent iPads that are "desktop-class browsing".
|
||||
// We can still detect them using their touchscreen, but this is a hack.
|
||||
// If mac laptops start to support touchscreens, this won't work anymore. Hence it's better
|
||||
// to test for the presence of a touchscreen if needed rather than checking if the device
|
||||
// is "mobile".
|
||||
return !!navigator.maxTouchPoints && navigator.maxTouchPoints > 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
let cachedIsMobile: boolean | null = null;
|
||||
/**
|
||||
* Check if the game runs on a mobile device (iPhone, iPad, Android).
|
||||
* Note that the distinction between what is a mobile device and what is not
|
||||
* is becoming blurry. If you use this for mobile controls,
|
||||
* prefer to check if the device has touchscreen support.
|
||||
*/
|
||||
export const isMobile = (): boolean => {
|
||||
if (cachedIsMobile !== null) {
|
||||
return cachedIsMobile;
|
||||
}
|
||||
return (cachedIsMobile = checkIsMobile());
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user