├── .gitattributes ├── .gitignore ├── .travis.yml ├── CMakeLists.txt ├── README.md ├── appveyor.yml ├── cmake ├── InputFilesList.cmake ├── MSVCRuntime.cmake ├── PDBUtils.cmake ├── Ternary.cmake └── WinXPSupport.cmake ├── resources └── scripts │ └── test.as └── src ├── AngelscriptUtils ├── .gitignore ├── ASUtilsConfig.h.in ├── CASLoggingContextResultHandler.cpp ├── CASLoggingContextResultHandler.h ├── CASManager.cpp ├── CASManager.h ├── CASModule.cpp ├── CASModule.h ├── CASModuleDescriptor.cpp ├── CASModuleDescriptor.h ├── CASModuleManager.cpp ├── CASModuleManager.h ├── CMakeLists.txt ├── IASContextResultHandler.h ├── IASInitializer.h ├── IASModuleBuilder.h ├── ScriptAPI │ ├── CASScheduler.cpp │ ├── CASScheduler.h │ ├── CMakeLists.txt │ └── Reflection │ │ ├── ASReflection.cpp │ │ ├── ASReflection.h │ │ ├── CASEngineReflectionGroup.cpp │ │ ├── CASEngineReflectionGroup.h │ │ ├── CASModuleReflectionGroup.cpp │ │ ├── CASModuleReflectionGroup.h │ │ ├── CMakeLists.txt │ │ └── IASReflectionGroup.h ├── add_on │ └── scriptbuilder │ │ ├── scriptbuilder.cpp │ │ └── scriptbuilder.h ├── cmake │ └── AngelscriptUtilsConfig.cmake ├── event │ ├── CASBaseEvent.cpp │ ├── CASBaseEvent.h │ ├── CASBaseEventCaller.h │ ├── CASEvent.cpp │ ├── CASEvent.h │ ├── CASEventCaller.cpp │ ├── CASEventCaller.h │ ├── CASEventManager.cpp │ ├── CASEventManager.h │ └── CMakeLists.txt ├── std_make_unique.h ├── util │ ├── ASExtendAdapter.cpp │ ├── ASExtendAdapter.h │ ├── ASLogging.cpp │ ├── ASLogging.h │ ├── ASPlatform.cpp │ ├── ASPlatform.h │ ├── ASUtil.cpp │ ├── ASUtil.h │ ├── CASBaseClass.h │ ├── CASExtendAdapter.h │ ├── CASObjPtr.h │ ├── CASRefPtr.h │ ├── CMakeLists.txt │ ├── ContextUtils.cpp │ ├── ContextUtils.h │ ├── IASExtendAdapter.h │ └── StringUtils.h └── wrapper │ ├── ASCallable.h │ ├── ASCallableConst.h │ ├── CASArguments.cpp │ ├── CASArguments.h │ ├── CASContext.cpp │ ├── CASContext.h │ └── CMakeLists.txt ├── AngelscriptUtilsTest ├── ASCBaseEntity.h ├── CBaseEntity.cpp ├── CBaseEntity.h ├── CMakeLists.txt ├── CScriptBaseEntity.h ├── Main.cpp └── add_on │ ├── scriptany │ ├── scriptany.cpp │ └── scriptany.h │ ├── scriptarray │ ├── scriptarray.cpp │ └── scriptarray.h │ ├── scriptdictionary │ ├── scriptdictionary.cpp │ └── scriptdictionary.h │ └── scriptstdstring │ ├── scriptstdstring.cpp │ ├── scriptstdstring.h │ └── scriptstdstring_utils.cpp └── CMakeLists.txt /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear in the root of a volume 35 | .DocumentRevisions-V100 36 | .fseventsd 37 | .Spotlight-V100 38 | .TemporaryItems 39 | .Trashes 40 | .VolumeIcon.icns 41 | 42 | # Directories potentially created on remote AFP share 43 | .AppleDB 44 | .AppleDesktop 45 | Network Trash Folder 46 | Temporary Items 47 | .apdisk 48 | 49 | *.suo 50 | *.log 51 | *.pdb 52 | *.lastbuildstate 53 | *.tlog 54 | *.obj 55 | *.cache 56 | *.db 57 | *.opendb 58 | 59 | Doxyfile 60 | 61 | bin/* 62 | bin_*/* 63 | docs/* 64 | 65 | #Ignore test build directory 66 | test*/* -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # Use the C base 2 | language: c 3 | 4 | # Linux - use Ubuntu 14.04 Trusty Tahr instead of 12.04 Precise Pengolin, this 5 | # is required for the correct version of libsdl2-dev. 6 | sudo: required 7 | dist: trusty 8 | 9 | # Linux - add the Ubuntu restricted tool chain to install GCC 5 and 6, also to 10 | # install the development package for SDL2 11 | addons: 12 | apt: 13 | sources: 14 | - ubuntu-toolchain-r-test 15 | packages: 16 | - libsdl2-dev 17 | - linux-libc-dev 18 | - gcc-5-multilib 19 | - g++-5-multilib 20 | - gcc-6-multilib 21 | - g++-6-multilib 22 | 23 | matrix: 24 | allow_failures: 25 | # Mac OS X Mavericks 10.9.5 (Xcode 6.1) 26 | - os: osx 27 | include: 28 | # Ubuntu 14.04 Trusty Tahr amd64 (Linux) GCC 5 29 | # Everything disabled 30 | - os: linux 31 | env: COMPILER=gcc-5 BUILD_RULES="" 32 | # Ubuntu 14.04 Trusty Tahr amd64 (Linux) GCC 6 33 | # Everything disabled 34 | - os: linux 35 | env: COMPILER=gcc-6 BUILD_RULES="" 36 | # Everything disabled 37 | - os: osx 38 | env: BUILD_RULES="" 39 | osx_image: beta-xcode6.1 40 | # Mac OS X Mavericks 10.9.5 (Xcode 6.1) 41 | # Opposing Force 42 | - os: osx 43 | env: BUILD_RULES="" 44 | osx_image: beta-xcode6.1 45 | 46 | before_install: 47 | - | 48 | if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then 49 | sudo dpkg --add-architecture i386 50 | sudo apt-get -qq update 51 | sudo apt-get install -y linux-libc-dev:i386 52 | else 53 | brew update 54 | fi 55 | 56 | install: 57 | # Prepare the dependencies, build and fake Steam common directories for Travis 58 | - DEPS_DIR="${TRAVIS_BUILD_DIR}/deps" 59 | - INSTALL_DIR="${TRAVIS_BUILD_DIR}/AngelscriptUtils_Install" 60 | - mkdir -p ${DEPS_DIR} && mkdir -p ${INSTALL_DIR} && mkdir -p ${INSTALL_DIR} && cd ${DEPS_DIR} 61 | # Get the latest CMake version 62 | - | 63 | if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then 64 | CMAKE_URL="http://www.cmake.org/files/v3.6/cmake-3.6.2-Linux-x86_64.tar.gz" 65 | mkdir cmake && travis_retry wget --no-check-certificate --quiet -O - ${CMAKE_URL} | tar --strip-components=1 -xz -C cmake 66 | export PATH=${DEPS_DIR}/cmake/bin:${PATH} 67 | else 68 | CMAKE_URL="http://www.cmake.org/files/v3.6/cmake-3.6.2-Darwin-x86_64.tar.gz" 69 | mkdir cmake && travis_retry wget --no-check-certificate --quiet -O - ${CMAKE_URL} | tar --strip-components=1 -xz -C cmake 70 | export PATH=${DEPS_DIR}/cmake/CMake.app/Contents/bin:${PATH} 71 | fi 72 | 73 | before_script: 74 | # Move to build directory 75 | - cd ${TRAVIS_BUILD_DIR} 76 | - mkdir build && cd build 77 | 78 | script: 79 | # Just execute the cmake and make commands 80 | - | 81 | if [[ "${COMPILER}" == "gcc-5" ]]; then 82 | cmake -DCMAKE_CXX_COMPILER="g++-5" -DCMAKE_C_COMPILER="gcc-5" -DCMAKE_INSTALL_PREFIX=${INSTALL_DIR} ${BUILD_RULES} .. 83 | elif [[ "${COMPILER}" == "gcc-6" ]]; then 84 | cmake -DCMAKE_CXX_COMPILER="g++-6" -DCMAKE_C_COMPILER="gcc-6" -DCMAKE_INSTALL_PREFIX=${INSTALL_DIR} ${BUILD_RULES} .. 85 | else 86 | cmake -DCMAKE_INSTALL_PREFIX=${INSTALL_DIR} ${BUILD_RULES} .. 87 | fi 88 | - make 89 | 90 | notifications: 91 | email: false 92 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ############################################################# 2 | # # 3 | # AngelscriptUtils CMake build file # 4 | # # 5 | ############################################################# 6 | cmake_minimum_required( VERSION 3.6 ) 7 | 8 | # Source additional modules from the "cmake" directory 9 | list( APPEND CMAKE_MODULE_PATH 10 | "${CMAKE_CURRENT_LIST_DIR}/cmake" 11 | ) 12 | 13 | include( InputFilesList ) 14 | include( MSVCRuntime ) 15 | include( PDBUtils ) 16 | include( WinXPSupport ) 17 | include( Ternary ) 18 | 19 | project( AngelscriptUtils LANGUAGES CXX ) 20 | 21 | set( MSVC_RUNTIME "dynamic" CACHE STRING "Runtime to use for MSVC" ) 22 | set_property( CACHE MSVC_RUNTIME PROPERTY STRINGS dynamic static ) 23 | 24 | string( TOUPPER ${MSVC_RUNTIME} MSVC_RUNTIME_CONFIG ) 25 | 26 | #C++11 support 27 | #Targets that use VS2013 are also supported, so C++14 cannot be used 28 | set( CMAKE_CXX_STANDARD 11 ) 29 | set( CMAKE_CXX_STANDARD_REQUIRED ON ) 30 | 31 | #Debug builds should have a distinct name. 32 | if( NOT CMAKE_DEBUG_POSTFIX ) 33 | set( CMAKE_DEBUG_POSTFIX d ) 34 | endif() 35 | 36 | ternary( LINUX_32BIT_FLAG UNIX "-m32" "" ) 37 | 38 | set( SHARED_COMPILE_FLAGS 39 | ${LINUX_32BIT_FLAG} 40 | ) 41 | 42 | #Set global compiler settings. 43 | if( MSVC ) 44 | #Warning level 4. Wall shows warnings in standard headers so we can't compile if that's enabled. 45 | #Treat warnings as errors. 46 | set( SHARED_COMPILE_FLAGS 47 | "${SHARED_COMPILE_FLAGS} /W4 /WX" 48 | ) 49 | else() 50 | #All warnings. 51 | #No unknown pragma directives. 52 | #No attributes. 53 | set( SHARED_COMPILE_FLAGS 54 | "${SHARED_COMPILE_FLAGS} -Wall -Wno-unknown-pragmas -Wno-attributes" 55 | ) 56 | endif() 57 | 58 | set( SHARED_LINK_FLAGS 59 | ${LINUX_32BIT_FLAG} 60 | ) 61 | 62 | set( SHARED_DEFS 63 | $<$:_CRT_SECURE_NO_WARNINGS> 64 | ) 65 | 66 | set( OUTPUT_DIR "${CMAKE_SOURCE_DIR}/test" CACHE PATH "Output directory for binaries" ) 67 | 68 | set( EXTERNAL_DIR "${CMAKE_SOURCE_DIR}/external" ) 69 | set( SRC_DIR "${CMAKE_SOURCE_DIR}/src" ) 70 | 71 | #Copy all resources to the destination directory 72 | message( STATUS "Copying resources..." ) 73 | file( COPY ${CMAKE_SOURCE_DIR}/resources DESTINATION ${OUTPUT_DIR} ) 74 | message( STATUS "Done" ) 75 | 76 | #include the subdirectory containing our libs 77 | add_subdirectory( src ) 78 | 79 | #Default to test project 80 | set_property( DIRECTORY ${CMAKE_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT AngelscriptUtilsTest ) 81 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This repository contains Angelscript utilities 2 | 3 | Uses Angelscript 2.31.1 4 | 5 | Build status 6 | 7 | | | Windows | Linux/OSX | 8 | |-------------|---------|-----------| 9 | | **master** | [![AppVeyor](https://ci.appveyor.com/api/projects/status/5cuoe54uh7bjksrw?svg=true)](https://ci.appveyor.com/project/SamVanheer/angelscriptutils) | [![Build Status](https://travis-ci.org/SamVanheer/AngelscriptUtils.svg?branch=master)](https://travis-ci.org/SamVanheer/AngelscriptUtils) | 10 | 11 | Note: you must define the AS_STRING_OBJNAME macro to the name of the string addon API name. This is provided to allow ease of change. The name used by the original addon code is "string". 12 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | # Use a VM with VS 2015 2 | os: Visual Studio 2015 3 | 4 | # Only target Windows 32 bits 5 | platform: Win32 6 | 7 | # Build in both Debug and Release configurations 8 | configuration: 9 | - Debug 10 | - Release 11 | 12 | # Build with all those possible configurations 13 | environment: 14 | matrix: 15 | - BUILD_RULES: 16 | 17 | before_build: 18 | # Appveyor uses CMake 2.8, we require at least 3.6, so make the update 19 | - ps: Write-Host "=== (1/4) Downloading CMake 3.6.2 ZIP for Windows 64 bits ===" -foregroundcolor green 20 | - ps: wget https://cmake.org/files/v3.6/cmake-3.6.2-win64-x64.zip -OutFile cmake.zip 21 | - ps: Write-Host "=== (2/4) Installing CMake ===" -foregroundcolor green 22 | - cmd: 7z x cmake.zip -o"." -y 23 | # Create the build directory and the install directory 24 | - ps: Write-Host "=== (3/4) Creating build and fake Steam common directory ===" -foregroundcolor green 25 | - md build 26 | - md AngelscriptUtils_Install 27 | 28 | build_script: 29 | - cd build 30 | - ps: Write-Host "=== (4/4) Building ===" -foregroundcolor green 31 | - ..\cmake-3.6.2-win64-x64\bin\cmake.exe -DCMAKE_INSTALL_PREFIX=..\AngelscriptUtils_Install %BUILD_RULES% -G"Visual Studio 14 2015" .. 32 | - msbuild AngelscriptUtils.sln /t:Rebuild /p:Configuration=%CONFIGURATION% /m /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" 33 | 34 | # If one job fail, mark the build as failed 35 | matrix: 36 | fast_finish: true 37 | 38 | # We don't have unit tests 39 | test: off 40 | 41 | # We don't do deploying yet 42 | deploy: off 43 | -------------------------------------------------------------------------------- /cmake/InputFilesList.cmake: -------------------------------------------------------------------------------- 1 | if( INPUTFILESLIST_INCLUDED ) 2 | return() 3 | endif() 4 | set( INPUTFILESLIST_INCLUDED true ) 5 | 6 | # 7 | # This file defines functions to build a list of source and include files to be used to create libraries and executables, and install files, respectively. 8 | # 9 | # Call add_sources with one or more source/header files to add them to the list of files. 10 | # Call preprocess_sources to generate a list of files to include in a library or executable. 11 | # Use the PREP_SRCS variable to include the list. 12 | # Call create_source_groups with the root directory for the files in the list after defining the library or executable to generate filters for Visual Studio that match the directory structure. 13 | # Call add_includes to add files to the list of files to install. 14 | # Call install_includes with the root directory for the files in the list after defining the library or executable to install the included files. 15 | # Call clear_sources to clear the sources list and prepare it for the next library or executable. 16 | # 17 | 18 | #! Gets the list of source files 19 | # \arg:dest_var Name of the variable that will contain the list 20 | function( get_sources dest_var ) 21 | get_property( is_defined GLOBAL PROPERTY SRCS_LIST DEFINED ) 22 | 23 | if( is_defined ) 24 | get_property( srcs GLOBAL PROPERTY SRCS_LIST ) 25 | set( ${dest_var} ${srcs} PARENT_SCOPE ) 26 | else() 27 | set( ${dest_var} PARENT_SCOPE ) 28 | endif() 29 | endfunction( get_sources ) 30 | 31 | #! Function to collect all the sources from sub-directories into a single list 32 | # Pass the file paths of source files relative to the CMakeLists that is calling this function 33 | function( add_sources ) 34 | get_property( is_defined GLOBAL PROPERTY SRCS_LIST DEFINED ) 35 | 36 | if( NOT is_defined ) 37 | define_property( GLOBAL PROPERTY SRCS_LIST 38 | BRIEF_DOCS "List of source files" 39 | FULL_DOCS "List of source files to be compiled in one library" 40 | ) 41 | endif() 42 | 43 | # make absolute paths 44 | set( SRCS ) 45 | foreach( s IN LISTS ARGN ) 46 | if( NOT IS_ABSOLUTE "${s}" ) 47 | get_filename_component( s "${s}" ABSOLUTE ) 48 | endif() 49 | list( APPEND SRCS "${s}" ) 50 | endforeach() 51 | 52 | # append to global list 53 | set_property( GLOBAL APPEND PROPERTY SRCS_LIST "${SRCS}" ) 54 | endfunction( add_sources ) 55 | 56 | #! Preprocess source files 57 | function( preprocess_sources ) 58 | set( PREP_SRCS PARENT_SCOPE ) 59 | get_property( SRCS GLOBAL PROPERTY SRCS_LIST ) 60 | 61 | foreach( s IN LISTS SRCS ) 62 | file( RELATIVE_PATH rs "${CMAKE_CURRENT_SOURCE_DIR}" "${s}" ) 63 | string( REGEX REPLACE "r$" "" o "${CMAKE_CURRENT_BINARY_DIR}/${rs}" ) 64 | add_custom_command( 65 | OUTPUT "${o}" 66 | COMMAND ${CMAKE_COMMAND} -E copy "${s}" "${o}" 67 | DEPENDS "${s}" 68 | COMMENT "Creating ${o}" 69 | VERBATIM 70 | ) 71 | list( APPEND PREP_SRCS "${s}" ) 72 | endforeach() 73 | 74 | set( PREP_SRCS ${PREP_SRCS} PARENT_SCOPE ) 75 | endfunction( preprocess_sources ) 76 | 77 | #! Create the source groups for source files 78 | # \arg:_src_root_path Root directory for the list of source files 79 | function( create_source_groups _src_root_path ) 80 | get_property( SRCS GLOBAL PROPERTY SRCS_LIST ) 81 | 82 | foreach( _source IN ITEMS ${SRCS} ) 83 | get_filename_component( _source_path "${_source}" PATH ) 84 | file( RELATIVE_PATH _source_path_rel "${_src_root_path}" "${_source_path}" ) 85 | string( REPLACE "/" "\\" _group_path "${_source_path_rel}" ) 86 | source_group( "${_group_path}" FILES "${_source}" ) 87 | endforeach() 88 | endfunction( create_source_groups ) 89 | 90 | #! Function to clear the sources list 91 | # Call once sources have been added to a target and source groups have been created 92 | function( clear_sources ) 93 | set_property( GLOBAL PROPERTY SRCS_LIST "" ) 94 | set( PREP_SRCS PARENT_SCOPE ) 95 | endfunction( clear_sources ) 96 | 97 | #! Function to add include files to a single list 98 | function( add_includes ) 99 | get_property( is_defined GLOBAL PROPERTY INCLUDES_LIST DEFINED ) 100 | if( NOT is_defined ) 101 | define_property( GLOBAL PROPERTY INCLUDES_LIST 102 | BRIEF_DOCS "List of include files" 103 | FULL_DOCS "List of include files to be compiled in one library" 104 | ) 105 | endif() 106 | 107 | # make absolute paths 108 | set( INCLUDES ) 109 | foreach( s IN LISTS ARGN ) 110 | if( NOT IS_ABSOLUTE "${s}" ) 111 | get_filename_component( s "${s}" ABSOLUTE ) 112 | endif() 113 | list( APPEND INCLUDES "${s}" ) 114 | endforeach() 115 | 116 | # append to global list 117 | set_property( GLOBAL APPEND PROPERTY INCLUDES_LIST "${INCLUDES}" ) 118 | endfunction( add_includes ) 119 | 120 | #! Function to install includes 121 | # \arg:_include_root_path Root directory for the list of include files 122 | # \param:COMPONENT Which component to install includes to 123 | function( install_includes _include_root_path ) 124 | cmake_parse_arguments( INSTALL_INCLUDES "" "COMPONENT" "" ${ARGN} ) 125 | 126 | if( INSTALL_INCLUDES_COMPONENT ) 127 | set( INSTALL_COMPONENT COMPONENT ${INSTALL_INCLUDES_COMPONENT} ) 128 | endif() 129 | 130 | get_property( INCLUDES GLOBAL PROPERTY INCLUDES_LIST ) 131 | 132 | foreach( _include IN ITEMS ${INCLUDES} ) 133 | get_filename_component( _include_path "${_include}" PATH ) 134 | file( RELATIVE_PATH _include_path_rel "${_include_root_path}" "${_include_path}" ) 135 | string( REPLACE "/" "\\" _group_path "${_include_path_rel}" ) 136 | install( FILES "${_include}" DESTINATION "include/${_group_path}" ${INSTALL_COMPONENT} ) 137 | endforeach() 138 | 139 | set_property( GLOBAL PROPERTY INCLUDES_LIST "" ) 140 | endfunction( install_includes ) 141 | -------------------------------------------------------------------------------- /cmake/MSVCRuntime.cmake: -------------------------------------------------------------------------------- 1 | if( MSVCRUNTIME_INCLUDED ) 2 | return() 3 | endif() 4 | set( MSVCRUNTIME_INCLUDED true ) 5 | 6 | #! Configures the runtime for the given target 7 | # Only one runtime can be provided 8 | # 9 | # \arg:target_name Name of the target whose runtime to configure 10 | # \flag:STATIC Whether to use the static runtime 11 | # \flag:DYNAMIC Whether to use the dynamic runtime 12 | # 13 | macro( configure_msvc_runtime target_name ) 14 | cmake_parse_arguments( ARG "STATIC;DYNAMIC" "" "" ${ARGN} ) 15 | 16 | if( ARG_UNPARSED_ARGUMENTS ) 17 | message( FATAL_ERROR "unrecognized arguments: ${ARG_UNPARSED_ARGUMENTS}" ) 18 | endif() 19 | 20 | if( ARG_STATIC AND ARG_DYNAMIC ) 21 | message( FATAL_ERROR "The STATIC and DYNAMIC runtimes are mutually exclusive" ) 22 | endif() 23 | 24 | if( MSVC ) 25 | # Set compiler options. 26 | if( ARG_STATIC ) 27 | target_compile_options( ${target_name} PRIVATE $<$:/MTd> ) 28 | target_compile_options( ${target_name} PRIVATE $<$>:/MT> ) 29 | elseif( ARG_DYNAMIC ) 30 | target_compile_options( ${target_name} PRIVATE $<$:/MDd> ) 31 | target_compile_options( ${target_name} PRIVATE $<$>:/MD> ) 32 | else() 33 | #Should never happen, but if more combinations are needed, this will cover edge cases. 34 | message( FATAL_ERROR "Unknown runtime selected" ) 35 | endif() 36 | endif() 37 | endmacro() 38 | -------------------------------------------------------------------------------- /cmake/PDBUtils.cmake: -------------------------------------------------------------------------------- 1 | if( PDBUTILS_INCLUDED ) 2 | return() 3 | endif() 4 | set( PDBUTILS_INCLUDED true ) 5 | 6 | #! Sets PDB file names to match the binaries 7 | # \arg:target_name Name of the target to configure PDB names for 8 | macro( set_pdb_names target_name ) 9 | foreach( config IN LISTS CMAKE_CONFIGURATION_TYPES ) 10 | #TODO: figure out if there's a way to check if a config is debug - Solokiller 11 | set( POSTFIX ) 12 | if( ${config} STREQUAL "Debug" ) 13 | set( POSTFIX ${CMAKE_DEBUG_POSTFIX} ) 14 | endif() 15 | 16 | string( TOUPPER ${config} PDB_POSTFIX ) 17 | 18 | set_target_properties( ${target_name} PROPERTIES COMPILE_PDB_NAME_${PDB_POSTFIX} "${target_name}${POSTFIX}" ) 19 | endforeach() 20 | endmacro( set_pdb_names ) 21 | 22 | #! Installs PDB files for a given target 23 | # \arg:target_name Name of the target to install PDB files for 24 | # \arg:destination Destination to install files to 25 | macro( install_pdbs target_name destination ) 26 | if( WIN32 ) 27 | foreach( config IN LISTS CMAKE_CONFIGURATION_TYPES ) 28 | #TODO: figure out if there's a way to check if a config is debug - Solokiller 29 | set( POSTFIX ) 30 | if( ${config} STREQUAL "Debug" ) 31 | set( POSTFIX ${CMAKE_DEBUG_POSTFIX} ) 32 | endif() 33 | 34 | install( FILES ${CMAKE_CURRENT_BINARY_DIR}/${config}/${target_name}${POSTFIX}.pdb DESTINATION ${destination} CONFIGURATIONS ${config} ) 35 | endforeach() 36 | endif() 37 | endmacro( install_pdbs ) 38 | -------------------------------------------------------------------------------- /cmake/Ternary.cmake: -------------------------------------------------------------------------------- 1 | if( TERNARY_INCLUDED ) 2 | return() 3 | endif() 4 | set( TERNARY_INCLUDED true ) 5 | 6 | #! Ternary operator 7 | # 8 | # \arg:result_var_name Name of the variable to assign the value to 9 | # \arg:condition Condition to evaluate 10 | # \arg:value_if_true Value to set if the condition is true 11 | # \arg:value_if_false Value to set if the condition is false 12 | macro( ternary result_var_name condition value_if_true value_if_false ) 13 | if( ${condition} ) 14 | set( ${result_var_name} ${value_if_true} ) 15 | else() 16 | set( ${result_var_name} ${value_if_false} ) 17 | endif() 18 | endmacro( ternary ) 19 | -------------------------------------------------------------------------------- /cmake/WinXPSupport.cmake: -------------------------------------------------------------------------------- 1 | if( WINXPSUPPORT_INCLUDED ) 2 | return() 3 | endif() 4 | set( WINXPSUPPORT_INCLUDED true ) 5 | 6 | if( MSVC ) 7 | set( WINXP_NOTIFY_THREADSAFE OFF CACHE BOOL "Enable to notify when targets have thread-safe initialization disabled" ) 8 | endif() 9 | 10 | #! Checks if thread-safe initialization needs to be disabled for the given target. 11 | # If targeting Windows XP (v*_xp toolset) and using an MSVC version of Visual Studio 2015 or newer, it is disabled. 12 | # \arg:target_name The name of the target to check 13 | # 14 | # If WINXP_NOTIFY_THREADSAFE is enabled, affected targets will be printed out 15 | macro( check_winxp_support target_name ) 16 | #Visual Studio only. 17 | if( MSVC ) 18 | #Verify that we have the data we need. 19 | if( NOT TARGET ${target_name} ) 20 | message( FATAL_ERROR "Target ${target_name} does not exist" ) 21 | endif() 22 | 23 | #VS2015 and newer requires this 24 | if( NOT "${MSVC_VERSION}" LESS 1900 AND CMAKE_VS_PLATFORM_TOOLSET MATCHES ".*_xp$" ) 25 | get_target_property( FLAGS ${target_name} COMPILE_FLAGS ) 26 | 27 | #Check if it's already set. Eliminates some noise in the output if it was explicitly disabled before 28 | if( ${FLAGS} STREQUAL "NOTFOUND" ) 29 | message( WARNING "Couldn't get compile flags from target ${target_name}" ) 30 | else() 31 | if( NOT FLAGS MATCHES "/Zc:threadSafeInit-" ) 32 | 33 | #Alert users if requested 34 | if( WINXP_NOTIFY_THREADSAFE ) 35 | message( STATUS "${target_name}: Disabling Thread-safe initialization for Windows XP support" ) 36 | endif() 37 | #Disable thread-safe init so Windows XP users don't get crashes. 38 | 39 | target_compile_options( ${target_name} PRIVATE 40 | /Zc:threadSafeInit- 41 | ) 42 | endif() 43 | endif() 44 | endif() 45 | endif() 46 | endmacro( check_winxp_support ) 47 | -------------------------------------------------------------------------------- /resources/scripts/test.as: -------------------------------------------------------------------------------- 1 | 2 | class CEntity : CScriptBaseEntity 3 | { 4 | void Spawn() 5 | { 6 | Print( "Spawned\n" ); 7 | } 8 | 9 | int ScheduleOfType( const string& in szName ) 10 | { 11 | return BaseClass.ScheduleOfType( szName ) + 2; 12 | } 13 | } 14 | 15 | enum E 16 | { 17 | VAL = 0, 18 | VAL2 19 | } 20 | 21 | class Foo 22 | { 23 | HookReturnCode Func( const string& in szString ) 24 | { 25 | Print( "method " + szString ); 26 | return HOOK_CONTINUE; 27 | } 28 | } 29 | 30 | funcdef void FuncPtr(); 31 | 32 | bool Function( int integer, Foo@ pFoo, E e, FuncPtr@ pFunc, const string& in szString, size_t size ) 33 | { 34 | Print( szString ); 35 | 36 | return true; 37 | } 38 | 39 | HookReturnCode MainFunc( const string& in szString ) 40 | { 41 | Print( "hook called\n" ); 42 | 43 | return HOOK_CONTINUE; 44 | } 45 | 46 | void Func( const string& in szString ) 47 | { 48 | Print( szString + "\n" ); 49 | } 50 | 51 | void NoArgs() 52 | { 53 | Print( "No arguments works\n" ); 54 | } 55 | 56 | class Lifetime 57 | { 58 | Lifetime() 59 | { 60 | Print( "Lifetime constructed\n" ); 61 | } 62 | 63 | ~Lifetime() 64 | { 65 | Print( "Lifetime destroyed\n" ); 66 | } 67 | } 68 | 69 | Lifetime@ GetLifetime() 70 | { 71 | return @Lifetime(); 72 | } 73 | 74 | void PrintReflection() 75 | { 76 | /* 77 | * Let's print out all global functions registered by the program. 78 | */ 79 | for( uint uiIndex = 0; uiIndex < Reflect::Engine.GetGlobalFunctionCount(); ++uiIndex ) 80 | { 81 | Reflect::Function@ pFunction = Reflect::Engine.GetGlobalFunctionByIndex( uiIndex ); 82 | 83 | Print( pFunction.GetNamespace() + "::" + pFunction.GetName() + "\n" ); 84 | } 85 | 86 | /* 87 | * Let's print out all object types and all of their method registered by the program. 88 | */ 89 | for( uint uiIndex = 0; uiIndex < Reflect::Engine.GetObjectTypeCount(); ++uiIndex ) 90 | { 91 | Reflect::TypeInfo@ pType = Reflect::Engine.GetObjectTypeByIndex( uiIndex ); 92 | 93 | Print( pType.GetNamespace() + "::" + pType.GetName() + "\n" ); 94 | 95 | for( uint uiIndex2 = 0; uiIndex2 < pType.GetMethodCount(); ++uiIndex2 ) 96 | { 97 | Reflect::Method@ pMethod = pType.GetMethodByIndex( uiIndex2 ); 98 | 99 | Print( pMethod.GetDeclaration( bIncludeObjectName: false, bIncludeParamNames: true ) + "\n" ); 100 | } 101 | } 102 | } 103 | 104 | namespace Foo 105 | { 106 | int Bar() 107 | { 108 | return 0; 109 | } 110 | 111 | class Baz 112 | { 113 | } 114 | } 115 | 116 | class HookEvent 117 | { 118 | HookReturnCode Hook( const string& in szString ) 119 | { 120 | Print( "HookEvent lookup works\n" ); 121 | 122 | g_EventManager.UnhookEvent( "Main", @MainHook( HookEvent().Hook ) ); 123 | 124 | return HOOK_CONTINUE; 125 | } 126 | } 127 | 128 | int main( const string& in szString, const bool bInEvent ) 129 | { 130 | Print( "foo\nbar\n" ); 131 | Print( szString ); 132 | 133 | if( !bInEvent ) 134 | { 135 | Events::Main.Hook( MainFunc ); 136 | Events::Main.Hook( @MainHook( Foo().Func ) ); 137 | 138 | g_EventManager.HookEvent( "Main", @MainHook( HookEvent().Hook ) ); 139 | } 140 | 141 | CEvent@ pEvent = g_EventManager.FindEventByName( "Main" ); 142 | 143 | Print( "Event was found: " + ( pEvent !is null ? "yes" : "no" ) + "\n" ); 144 | 145 | dictionary foo; 146 | 147 | foo.set( "bar", @MainHook( @Foo().Func ) ); 148 | 149 | MainHook@ pFunc; 150 | 151 | foo.get( "bar", @pFunc ); 152 | 153 | pFunc( "test\n" ); 154 | 155 | Scheduler.SetTimeout( "Func", 5, "what's going on" ); 156 | 157 | //PrintReflection(); 158 | 159 | //Find a function in a namespace (Module). 160 | Reflect::Function@ pFunction = Reflect::Module.FindGlobalFunction( "Foo::Bar" ); 161 | 162 | Print( "(Module) Found function by name: " + ( ( pFunction !is null ) ? "yes" : "no" ) + "\n" ); 163 | 164 | @pFunction = Reflect::Module.FindGlobalFunction( "int Foo::Bar()", true ); 165 | 166 | Print( "(Module) Found function by decl: " + ( ( pFunction !is null ) ? "yes" : "no" ) + "\n" ); 167 | 168 | //Test for nonexistent. 169 | @pFunction = Reflect::Module.FindGlobalFunction( "Foo2::Bar" ); 170 | 171 | Print( "(Module) Didn't find function by name: " + ( ( pFunction is null ) ? "yes" : "no" ) + "\n" ); 172 | 173 | @pFunction = Reflect::Module.FindGlobalFunction( "int Foo2::Bar()", true ); 174 | 175 | Print( "(Module) Didn't find function by decl: " + ( ( pFunction is null ) ? "yes" : "no" ) + "\n" ); 176 | 177 | //Find a type in a namespace (Module). 178 | Reflect::TypeInfo@ pType = Reflect::Module.FindTypeInfo( "Foo::Baz" ); 179 | 180 | Print( "(Module) Found type info by name: " + ( ( pType !is null ) ? "yes" : "no" ) + "\n" ); 181 | 182 | @pType = Reflect::Module.FindTypeInfo( "Foo::Baz", true ); 183 | 184 | Print( "(Module) Found type info by decl: " + ( ( pType !is null ) ? "yes" : "no" ) + "\n" ); 185 | 186 | //Test for nonexistent. 187 | @pType = Reflect::Module.FindTypeInfo( "Foo2::Baz" ); 188 | 189 | Print( "(Module) Didn't find type info by name: " + ( ( pType is null ) ? "yes" : "no" ) + "\n" ); 190 | 191 | @pType = Reflect::Module.FindTypeInfo( "Foo2::Baz", true ); 192 | 193 | Print( "(Module) Didn't find type info by decl: " + ( ( pType is null ) ? "yes" : "no" ) + "\n" ); 194 | 195 | //Find a function in a namespace (Engine). 196 | @pFunction = Reflect::Engine.FindGlobalFunction( "NS::NSTest" ); 197 | 198 | Print( "(Engine) Found function by name: " + ( ( pFunction !is null ) ? "yes" : "no" ) + "\n" ); 199 | 200 | @pFunction = Reflect::Engine.FindGlobalFunction( "int NS::NSTest()", true ); 201 | 202 | Print( "(Engine) Found function by decl: " + ( ( pFunction !is null ) ? "yes" : "no" ) + "\n" ); 203 | 204 | //Test for nonexistent. 205 | @pFunction = Reflect::Engine.FindGlobalFunction( "Foo2::Bar" ); 206 | 207 | Print( "(Engine) Didn't find function by name: " + ( ( pFunction is null ) ? "yes" : "no" ) + "\n" ); 208 | 209 | @pFunction = Reflect::Engine.FindGlobalFunction( "int Foo2::Bar()", true ); 210 | 211 | Print( "(Engine) Didn't find function by decl: " + ( ( pFunction is null ) ? "yes" : "no" ) + "\n" ); 212 | 213 | //Find a type in a namespace (Engine). 214 | @pType = Reflect::Engine.FindTypeInfo( "Reflect::TypeInfo" ); 215 | 216 | Print( "(Engine) Found type info by name: " + ( ( pType !is null ) ? "yes" : "no" ) + "\n" ); 217 | 218 | @pType = Reflect::Engine.FindTypeInfo( "Reflect::TypeInfo", true ); 219 | 220 | Print( "(Engine) Found type info by decl: " + ( ( pType !is null ) ? "yes" : "no" ) + "\n" ); 221 | 222 | //Test for nonexistent. 223 | @pType = Reflect::Engine.FindTypeInfo( "Foo2::Baz" ); 224 | 225 | Print( "(Engine) Didn't find type info by name: " + ( ( pType is null ) ? "yes" : "no" ) + "\n" ); 226 | 227 | @pType = Reflect::Engine.FindTypeInfo( "Foo2::Baz", true ); 228 | 229 | Print( "(Engine) Didn't find type info by decl: " + ( ( pType is null ) ? "yes" : "no" ) + "\n" ); 230 | 231 | return 1; 232 | } 233 | 234 | //This function deliberately triggers a null pointer exception so the context result handler can log it. 235 | void DoNullPointerException() 236 | { 237 | dictionary@ pDict = null; 238 | 239 | Print( "checking null pointer\n" ); 240 | Print( "Value: " + pDict.getKeys()[ 0 ] + "\n" ); 241 | } 242 | 243 | //This function deliberately triggers a null pointer exception so the context result handler can log it. Object member function version to format it differently. 244 | namespace Naaa 245 | { 246 | class NullAccess 247 | { 248 | void TryAccess() 249 | { 250 | dictionary@ pDict = null; 251 | 252 | Print( "checking null pointer\n" ); 253 | Print( "Value: " + pDict.getKeys()[ 0 ] + "\n" ); 254 | } 255 | } 256 | } 257 | 258 | void DoNullPointerException2() 259 | { 260 | Naaa::NullAccess().TryAccess(); 261 | } 262 | -------------------------------------------------------------------------------- /src/AngelscriptUtils/.gitignore: -------------------------------------------------------------------------------- 1 | # This is a generated file 2 | ASUtilsConfig.h 3 | -------------------------------------------------------------------------------- /src/AngelscriptUtils/ASUtilsConfig.h.in: -------------------------------------------------------------------------------- 1 | #ifndef ANGELSCRIPTUTILS_CONFIG_H 2 | #define ANGELSCRIPTUTILS_CONFIG_H 3 | 4 | #include 5 | 6 | /** 7 | * @file 8 | * 9 | * Configuration file for AngelscriptUtils 10 | * 11 | * Autogenerated by CMake, do not edit directly 12 | */ 13 | 14 | /** 15 | * @brief The user data ID for the CASModule instance in asIScriptModule 16 | */ 17 | const asPWORD ASUTILS_CASMODULE_USER_DATA_ID = @ASUTILS_CASMODULE_USER_DATA_ID@; 18 | 19 | /** 20 | * @brief The user data key for the context result handler user data entry 21 | */ 22 | const asPWORD ASUTILS_CONTEXT_RESULTHANDLER_USERDATA_ID = @ASUTILS_CONTEXT_RESULTHANDLER_USERDATA_ID@; 23 | 24 | #endif //ANGELSCRIPTUTILS_CONFIG_H 25 | -------------------------------------------------------------------------------- /src/AngelscriptUtils/CASLoggingContextResultHandler.cpp: -------------------------------------------------------------------------------- 1 | #include "util/ASUtil.h" 2 | 3 | #include "CASLoggingContextResultHandler.h" 4 | 5 | CASLoggingContextResultHandler::CASLoggingContextResultHandler( const Flags_t flags ) 6 | { 7 | SetFlags( flags ); 8 | } 9 | 10 | void CASLoggingContextResultHandler::ProcessPrepareResult( asIScriptFunction&, asIScriptContext&, int iResult ) 11 | { 12 | if( iResult < 0 ) 13 | { 14 | switch( iResult ) 15 | { 16 | case asCONTEXT_ACTIVE: 17 | { 18 | as::log->error( "Tried to prepare context that is currently executing or suspended" ); 19 | break; 20 | } 21 | 22 | //This can't happen without throwing an exception when passing the function into as::Call since it dereferences the pointer. 23 | case asNO_FUNCTION: 24 | { 25 | as::log->error( "Tried to prepare null function" ); 26 | break; 27 | } 28 | 29 | case asINVALID_ARG: 30 | { 31 | as::log->error( "Tried to prepare context with function from different engine" ); 32 | break; 33 | } 34 | 35 | case asOUT_OF_MEMORY: 36 | { 37 | as::log->error( "Ran out of memory while preparing context for execution" ); 38 | break; 39 | } 40 | 41 | default: 42 | { 43 | as::log->error( "Unknown error \"{}\" occurred while preparing context for execution", iResult ); 44 | break; 45 | } 46 | } 47 | } 48 | } 49 | 50 | void CASLoggingContextResultHandler::ProcessExecuteResult( asIScriptFunction& function, asIScriptContext& context, int iResult ) 51 | { 52 | if( iResult != asEXECUTION_FINISHED ) 53 | { 54 | const auto szFunctionName = as::FormatFunctionName( function ); 55 | 56 | switch( iResult ) 57 | { 58 | case asEXECUTION_SUSPENDED: 59 | { 60 | //Suspended execution is an error if the user wants it to be. 61 | if( m_Flags & Flag::SUSPEND_IS_ERROR ) 62 | { 63 | as::log->error( "Script execution unexpectedly suspended while executing function \"{}\"", szFunctionName ); 64 | 65 | LogCurrentFunction( context, "Suspended" ); 66 | } 67 | 68 | break; 69 | } 70 | 71 | case asCONTEXT_NOT_PREPARED: 72 | { 73 | as::log->error( "Context not prepared to execute function \"{}\"", szFunctionName ); 74 | break; 75 | } 76 | 77 | case asEXECUTION_ABORTED: 78 | { 79 | as::log->error( "Script execution aborted while executing function \"{}\"", szFunctionName ); 80 | 81 | LogCurrentFunction( context, "Aborted" ); 82 | 83 | break; 84 | } 85 | 86 | case asEXECUTION_EXCEPTION: 87 | { 88 | const auto szExceptionFunction = as::FormatFunctionName( *context.GetExceptionFunction() ); 89 | 90 | int iColumn = 0; 91 | const char* pszSection = nullptr; 92 | 93 | const int iLineNumber = context.GetExceptionLineNumber( &iColumn, &pszSection ); 94 | 95 | as::log->warn( 96 | "Exception occurred while executing function \"{}\"\nFunction \"{}\" at line {}, column {} in section \"{}\":\n{}", 97 | szFunctionName, szExceptionFunction, iLineNumber, iColumn, pszSection, context.GetExceptionString() 98 | ); 99 | 100 | break; 101 | } 102 | 103 | //Unexpected error states. 104 | case asEXECUTION_FINISHED: 105 | case asEXECUTION_PREPARED: 106 | case asEXECUTION_UNINITIALIZED: 107 | case asEXECUTION_ACTIVE: 108 | case asEXECUTION_ERROR: 109 | { 110 | as::log->error( "Unexpected context state \"{}\" encountered while executing function \"{}\"", iResult, szFunctionName ); 111 | break; 112 | } 113 | 114 | //Unknown error. 115 | default: 116 | case asERROR: 117 | { 118 | as::log->error( "Unknown error \"{}\" occurred while executing function \"{}\"\n", iResult, szFunctionName ); 119 | break; 120 | } 121 | } 122 | } 123 | } 124 | 125 | void CASLoggingContextResultHandler::ProcessUnprepareResult( asIScriptContext&, int iResult ) 126 | { 127 | if( iResult < 0 ) 128 | { 129 | switch( iResult ) 130 | { 131 | //This can happen if a longjmp occurs while executing a script. The context state is corrupted after such a call. 132 | case asCONTEXT_ACTIVE: 133 | { 134 | as::log->error( "Tried to unprepare context that is still active" ); 135 | break; 136 | } 137 | 138 | default: 139 | { 140 | as::log->error( "Unknown error \"{}\" occurred while unpreparing", iResult ); 141 | break; 142 | } 143 | } 144 | } 145 | } 146 | 147 | void CASLoggingContextResultHandler::LogCurrentFunction( asIScriptContext& context, const char* const pszAction ) 148 | { 149 | assert( pszAction ); 150 | assert( *pszAction ); 151 | 152 | as::CASCallerInfo info; 153 | 154 | as::GetCallerInfo( info, &context ); 155 | 156 | auto pCurrentFunc = context.GetFunction( context.GetCallstackSize() - 1 ); 157 | 158 | if( pCurrentFunc ) 159 | { 160 | const auto szFunctionName = as::FormatFunctionName( *pCurrentFunc ); 161 | 162 | as::log->error( "{} while in function \"{}\" at line {}, column {} in section \"{}\"", pszAction, szFunctionName, info.iLine, info.iColumn, info.pszSection ); 163 | } 164 | else 165 | { 166 | as::log->error( "{} in unknown function", pszAction ); 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /src/AngelscriptUtils/CASLoggingContextResultHandler.h: -------------------------------------------------------------------------------- 1 | #ifndef CASLOGGINGCONTEXTRESULTHANDLER_H 2 | #define CASLOGGINGCONTEXTRESULTHANDLER_H 3 | 4 | #include 5 | 6 | #include "util/CASBaseClass.h" 7 | 8 | #include "IASContextResultHandler.h" 9 | 10 | /** 11 | * Context result handler that logs all errors to the default logger. 12 | * Suspended contexts are treated as normal behavior by default, unless the Flag::SUSPEND_IS_ERROR flag is set. 13 | */ 14 | class CASLoggingContextResultHandler : public IASContextResultHandler, public CASAtomicRefCountedBaseClass 15 | { 16 | public: 17 | using Flags_t = uint32_t; 18 | 19 | struct Flag 20 | { 21 | enum EFlag : Flags_t 22 | { 23 | NONE = 0, 24 | 25 | /** 26 | * Suspended contexts should be treated as errors. 27 | */ 28 | SUSPEND_IS_ERROR = 1 << 0, 29 | }; 30 | }; 31 | 32 | public: 33 | /** 34 | * @param flags Handler flags. 35 | */ 36 | CASLoggingContextResultHandler( const Flags_t flags = Flag::NONE ); 37 | 38 | void AddRef() const override 39 | { 40 | CASAtomicRefCountedBaseClass::AddRef(); 41 | } 42 | 43 | void Release() const override 44 | { 45 | if( InternalRelease() ) 46 | delete this; 47 | } 48 | 49 | void ProcessPrepareResult( asIScriptFunction& function, asIScriptContext& context, int iResult ) override; 50 | 51 | void ProcessExecuteResult( asIScriptFunction& function, asIScriptContext& context, int iResult ) override; 52 | 53 | void ProcessUnprepareResult( asIScriptContext& context, int iResult ) override; 54 | 55 | Flags_t GetFlags() const { return m_Flags; } 56 | 57 | void SetFlags( const Flags_t flags ) 58 | { 59 | m_Flags = flags; 60 | } 61 | 62 | private: 63 | void LogCurrentFunction( asIScriptContext& context, const char* const pszAction ); 64 | 65 | private: 66 | Flags_t m_Flags; 67 | 68 | private: 69 | CASLoggingContextResultHandler( const CASLoggingContextResultHandler& ) = delete; 70 | CASLoggingContextResultHandler& operator=( const CASLoggingContextResultHandler& ) = delete; 71 | }; 72 | 73 | #endif //CASLOGGINGCONTEXTRESULTHANDLER_H 74 | -------------------------------------------------------------------------------- /src/AngelscriptUtils/CASManager.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include "ASUtilsConfig.h" 9 | 10 | #include "util/ASLogging.h" 11 | #include "util/ASUtil.h" 12 | 13 | #include "IASContextResultHandler.h" 14 | #include "IASInitializer.h" 15 | 16 | #include "CASManager.h" 17 | 18 | #include "std_make_unique.h" 19 | 20 | CASManager* CASManager::m_pActiveManager = nullptr; 21 | 22 | CASManager* CASManager::GetActiveManager() 23 | { 24 | assert( m_pActiveManager ); 25 | 26 | return m_pActiveManager; 27 | } 28 | 29 | void CASManager::ActivateManager( CASManager* pManager ) 30 | { 31 | m_pActiveManager = pManager; 32 | } 33 | 34 | void CASManager::Activate() 35 | { 36 | ActivateManager( this ); 37 | } 38 | 39 | void CASManager::Deactivate() 40 | { 41 | if( this == m_pActiveManager ) 42 | { 43 | m_pActiveManager = nullptr; 44 | } 45 | } 46 | 47 | CASManager::CASManager() 48 | { 49 | } 50 | 51 | CASManager::~CASManager() 52 | { 53 | assert( !m_pScriptEngine ); 54 | } 55 | 56 | //Used to caller OnInitEnd autmatically. 57 | struct InitEndCaller 58 | { 59 | IASInitializer& initializer; 60 | bool bSuccess = false; 61 | 62 | InitEndCaller( IASInitializer& initializer ) 63 | : initializer( initializer ) 64 | { 65 | } 66 | 67 | ~InitEndCaller() 68 | { 69 | initializer.OnInitEnd( bSuccess ); 70 | } 71 | 72 | private: 73 | InitEndCaller( const InitEndCaller& ) = delete; 74 | InitEndCaller& operator=( const InitEndCaller& ) = delete; 75 | }; 76 | 77 | bool CASManager::Initialize( IASInitializer& initializer ) 78 | { 79 | if( !as::log ) 80 | { 81 | as::log = spdlog::create( "ASUtils" ); 82 | } 83 | 84 | if( m_pScriptEngine ) 85 | { 86 | return true; 87 | } 88 | 89 | m_pScriptEngine = asCreateScriptEngine( ANGELSCRIPT_VERSION ); 90 | 91 | if( !m_pScriptEngine ) 92 | { 93 | return false; 94 | } 95 | 96 | InitEndCaller initEndCaller( initializer ); 97 | 98 | initializer.OnInitBegin(); 99 | 100 | //Set the cleanup callback for the result handler. 101 | m_pScriptEngine->SetContextUserDataCleanupCallback( as::FreeContextResultHandler, ASUTILS_CONTEXT_RESULTHANDLER_USERDATA_ID ); 102 | 103 | const bool bUseEventManager = initializer.UseEventManager(); 104 | 105 | if( bUseEventManager ) 106 | { 107 | m_EventManager = std::make_unique( *m_pScriptEngine, initializer.GetEventNamespace() ); 108 | } 109 | 110 | m_ModuleManager = std::make_unique( *m_pScriptEngine, m_EventManager ); 111 | 112 | asSFuncPtr msgCallback; 113 | void* pObj; 114 | asDWORD callConv; 115 | 116 | if( !initializer.GetMessageCallback( msgCallback, pObj, callConv ) ) 117 | { 118 | msgCallback = asMETHOD( CASManager, MessageCallback ); 119 | pObj = this; 120 | callConv = asCALL_THISCALL; 121 | } 122 | 123 | m_pScriptEngine->SetMessageCallback( msgCallback, pObj, callConv ); 124 | 125 | Activate(); 126 | 127 | if( !initializer.RegisterCoreAPI( *this ) ) 128 | return false; 129 | 130 | if( bUseEventManager ) 131 | { 132 | if( !initializer.AddEvents( *this, *m_EventManager ) ) 133 | return false; 134 | 135 | //Registers all events. One-time event that happens on startup. 136 | m_EventManager->RegisterEvents( *GetEngine() ); 137 | } 138 | 139 | if( !initializer.RegisterAPI( *this ) ) 140 | return false; 141 | 142 | initEndCaller.bSuccess = true; 143 | 144 | return true; 145 | } 146 | 147 | void CASManager::Shutdown() 148 | { 149 | if( !m_pScriptEngine ) 150 | { 151 | return; 152 | } 153 | 154 | Activate(); 155 | 156 | if( m_EventManager ) 157 | { 158 | //Unhook all functions to prevent dangling pointers. 159 | m_EventManager->UnhookAllFunctions(); 160 | 161 | m_EventManager.reset(); 162 | } 163 | 164 | if( m_ModuleManager ) 165 | { 166 | //Clear all modules and destroy all descriptors. 167 | m_ModuleManager->Clear(); 168 | m_ModuleManager.reset(); 169 | } 170 | 171 | //Let it go. 172 | m_pScriptEngine->ShutDownAndRelease(); 173 | m_pScriptEngine = nullptr; 174 | 175 | Deactivate(); 176 | } 177 | 178 | void CASManager::MessageCallback( const asSMessageInfo* pMsg ) 179 | { 180 | const char* pType = ""; 181 | 182 | //Get the prefix. 183 | switch( pMsg->type ) 184 | { 185 | case asMSGTYPE_ERROR: pType = "Error: "; break; 186 | case asMSGTYPE_WARNING: pType = "Warning: "; break; 187 | default: break; 188 | } 189 | 190 | //Only display the section if it was actually set. Some messages are not triggered by script code compilation or execution. 191 | const bool bHasSection = pMsg->section && *pMsg->section; 192 | 193 | bool bNeedsNewline = false; 194 | 195 | if( bHasSection ) 196 | { 197 | std::cout << "Section \"" << pMsg->section << "\""; 198 | bNeedsNewline = true; 199 | } 200 | 201 | //Some messages don't refer to script code, and set both to 0. 202 | if( pMsg->row != 0 && pMsg->col != 0 ) 203 | { 204 | if( bHasSection ) 205 | std::cout << ' '; 206 | 207 | std::cout << "(" << pMsg->row << ", " << pMsg->col << ")"; 208 | bNeedsNewline = true; 209 | } 210 | 211 | if( bNeedsNewline ) 212 | std::cout << std::endl; 213 | 214 | std::cout << pType << pMsg->message << std::endl; 215 | } 216 | -------------------------------------------------------------------------------- /src/AngelscriptUtils/CASManager.h: -------------------------------------------------------------------------------- 1 | #ifndef ANGELSCRIPT_CASMANAGER_H 2 | #define ANGELSCRIPT_CASMANAGER_H 3 | 4 | #include 5 | 6 | #include "util/ASPlatform.h" 7 | 8 | #include "CASModuleManager.h" 9 | #include "event/CASEventManager.h" 10 | 11 | class asIScriptEngine; 12 | struct asSMessageInfo; 13 | 14 | class IASInitializer; 15 | 16 | /** 17 | * @defgroup ASManager Angelscript Manager 18 | * 19 | * @{ 20 | */ 21 | 22 | /** 23 | * Manages the Angelscript engine instance, the module and event managers. 24 | * Multiple instances of this class can exist. In that case, you will have to activate the manager before using it. 25 | * Code that accesses the active manager will need it to be activated in order to work properly. 26 | */ 27 | class CASManager final 28 | { 29 | public: 30 | /** 31 | * Gets the currently active manager. 32 | * @see ActivateManager 33 | * @see Activate 34 | */ 35 | static CASManager* GetActiveManager(); 36 | 37 | /** 38 | * Makes the given manager the active manager. Can be null. 39 | */ 40 | static void ActivateManager( CASManager* pManager ); 41 | 42 | /** 43 | * Makes this the active manager. 44 | */ 45 | void Activate(); 46 | 47 | /** 48 | * If this manager is the active manager, deactivates it. 49 | */ 50 | void Deactivate(); 51 | 52 | /** 53 | * Constructor. 54 | */ 55 | CASManager(); 56 | 57 | /** 58 | * Destructor. 59 | */ 60 | ~CASManager(); 61 | 62 | /** 63 | * @return The script engine. 64 | */ 65 | asIScriptEngine* GetEngine() { return m_pScriptEngine; } 66 | 67 | /** 68 | * @return The module manager. 69 | */ 70 | CASModuleManager& GetModuleManager() { return *m_ModuleManager; } 71 | 72 | /** 73 | * @return The event manager. 74 | */ 75 | CASEventManager* GetEventManager() { return m_EventManager.get(); } 76 | 77 | /** 78 | * Initializes the manager. 79 | * On success, makes this the active manager. 80 | * @param initializer Initializer to use. 81 | * @return true on success, false otherwise. 82 | */ 83 | bool Initialize( IASInitializer& initializer ); 84 | 85 | /** 86 | * Shuts down the manager. 87 | * Will set the active manager to null. 88 | */ 89 | void Shutdown(); 90 | 91 | private: 92 | /** 93 | * @see asIScriptEngine::SetMessageCallback 94 | */ 95 | void MessageCallback( const asSMessageInfo* pMsg ); 96 | 97 | private: 98 | static CASManager* m_pActiveManager; 99 | 100 | asIScriptEngine* m_pScriptEngine = nullptr; 101 | 102 | std::unique_ptr m_ModuleManager; 103 | std::shared_ptr m_EventManager; 104 | 105 | private: 106 | CASManager( const CASManager& ) = delete; 107 | CASManager& operator=( const CASManager& ) = delete; 108 | }; 109 | 110 | /** @} */ 111 | 112 | #endif //ANGELSCRIPT_CASMANAGER_H -------------------------------------------------------------------------------- /src/AngelscriptUtils/CASModule.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include "ScriptAPI/CASScheduler.h" 6 | 7 | #include "CASModule.h" 8 | 9 | CASModule::CASModule( asIScriptModule* pModule, const CASModuleDescriptor& descriptor, IASModuleUserData* pUserData ) 10 | : m_pModule( pModule ) 11 | , m_pDescriptor( &descriptor ) 12 | , m_pScheduler( new CASScheduler( *this ) ) 13 | , m_pUserData( pUserData ) 14 | { 15 | assert( pModule ); 16 | 17 | pModule->SetUserData( this, ASUTILS_CASMODULE_USER_DATA_ID ); 18 | } 19 | 20 | CASModule::~CASModule() 21 | { 22 | SetUserData( nullptr ); 23 | 24 | //Discard should've been called first. 25 | assert( !m_pModule ); 26 | 27 | //Delete last, in case code calls it during destruction 28 | delete m_pScheduler; 29 | } 30 | 31 | void CASModule::Release() const 32 | { 33 | if( InternalRelease() ) 34 | { 35 | delete this; 36 | } 37 | } 38 | 39 | void CASModule::Discard() 40 | { 41 | //Clears out the functions that might be holding references to this module 42 | m_pScheduler->ClearTimerList(); 43 | 44 | if( m_pModule ) 45 | { 46 | m_pModule->Discard(); 47 | m_pModule = nullptr; 48 | } 49 | } 50 | 51 | const char* CASModule::GetModuleName() const 52 | { 53 | assert( m_pModule ); 54 | 55 | return m_pModule->GetName(); 56 | } 57 | 58 | CASModule* GetModuleFromScriptModule( const asIScriptModule* pModule ) 59 | { 60 | assert( pModule ); 61 | 62 | return reinterpret_cast( pModule->GetUserData( ASUTILS_CASMODULE_USER_DATA_ID ) ); 63 | } 64 | 65 | CASModule* GetModuleFromScriptFunction( const asIScriptFunction* pFunction ) 66 | { 67 | assert( pFunction ); 68 | 69 | auto pDelegate = pFunction->GetDelegateFunction(); 70 | 71 | auto pFunc = pDelegate ? pDelegate : pFunction; 72 | 73 | auto pModule = GetModuleFromScriptModule( pFunc->GetModule() ); 74 | 75 | return pModule; 76 | } 77 | 78 | CASModule* GetModuleFromScriptContext( asIScriptContext* pContext ) 79 | { 80 | assert( pContext ); 81 | 82 | auto pFunction = pContext->GetFunction( pContext->GetCallstackSize() - 1 ); 83 | 84 | if( !pFunction ) 85 | return nullptr; 86 | 87 | return GetModuleFromScriptFunction( pFunction ); 88 | } 89 | 90 | asIScriptModule* GetScriptModuleFromScriptContext( asIScriptContext* pContext ) 91 | { 92 | assert( pContext ); 93 | 94 | auto pFunction = pContext->GetFunction( pContext->GetCallstackSize() - 1 ); 95 | 96 | if( !pFunction ) 97 | return nullptr; 98 | 99 | return pFunction->GetModule(); 100 | } 101 | -------------------------------------------------------------------------------- /src/AngelscriptUtils/CASModule.h: -------------------------------------------------------------------------------- 1 | #ifndef ANGELSCRIPT_CASMODULE_H 2 | #define ANGELSCRIPT_CASMODULE_H 3 | 4 | #include 5 | 6 | #include "ASUtilsConfig.h" 7 | 8 | #include "util/CASBaseClass.h" 9 | 10 | #include "CASModuleDescriptor.h" 11 | 12 | class asIScriptModule; 13 | class CASScheduler; 14 | 15 | /** 16 | * @defgroup ASModule Angelscript Module 17 | * 18 | * @{ 19 | */ 20 | 21 | /** 22 | * Interface that user data assigned to modules must implement. 23 | */ 24 | class IASModuleUserData 25 | { 26 | public: 27 | virtual ~IASModuleUserData(); 28 | 29 | /** 30 | * Called by the module when user data is being released. The module no longer references this user data after this call. 31 | */ 32 | virtual void Release() const = 0; 33 | }; 34 | 35 | inline IASModuleUserData::~IASModuleUserData() 36 | { 37 | } 38 | 39 | /** 40 | * Angelscript module. Wraps asIScriptModule and provides the descriptor. 41 | * Is reference counted, unlike the script module. 42 | */ 43 | class CASModule final : public CASAtomicRefCountedBaseClass 44 | { 45 | public: 46 | /** 47 | * Constructor. 48 | * @param pModule Script module. 49 | * @param descriptor Descriptor for this module. 50 | * @param pUserData Optional. User data to associate with this module. 51 | */ 52 | CASModule( asIScriptModule* pModule, const CASModuleDescriptor& descriptor, IASModuleUserData* pUserData = nullptr ); 53 | 54 | /** 55 | * Destructor. 56 | */ 57 | ~CASModule(); 58 | 59 | void Release() const; 60 | 61 | /** 62 | * Discards the module. It can no longer be used after this. 63 | */ 64 | void Discard(); 65 | 66 | /** 67 | * @return The script module. 68 | */ 69 | asIScriptModule* GetModule() { return m_pModule; } 70 | 71 | /** 72 | * @return The module name. 73 | */ 74 | const char* GetModuleName() const; 75 | 76 | /** 77 | * @return The descriptor. 78 | */ 79 | const CASModuleDescriptor& GetDescriptor() const { return *m_pDescriptor; } 80 | 81 | /** 82 | * @return The scheduler. 83 | */ 84 | CASScheduler* GetScheduler() { return m_pScheduler; } 85 | 86 | /** 87 | * @return User data associated with this module. 88 | */ 89 | IASModuleUserData* GetUserData() { return m_pUserData; } 90 | 91 | /** 92 | * Sets the user data associated with this module. 93 | */ 94 | void SetUserData( IASModuleUserData* pUserData ) 95 | { 96 | if( m_pUserData ) 97 | m_pUserData->Release(); 98 | 99 | m_pUserData = pUserData; 100 | } 101 | 102 | private: 103 | asIScriptModule* m_pModule; 104 | 105 | const CASModuleDescriptor* m_pDescriptor; 106 | 107 | CASScheduler* m_pScheduler; 108 | 109 | IASModuleUserData* m_pUserData = nullptr; 110 | 111 | private: 112 | CASModule( const CASModule& ) = delete; 113 | CASModule& operator=( const CASModule& ) = delete; 114 | }; 115 | 116 | /** 117 | * Gets a module from a script module. 118 | * @param pModule Script module to retrieve the module from. 119 | * @return The module, or null if it couldn't be retrieved. 120 | */ 121 | CASModule* GetModuleFromScriptModule( const asIScriptModule* pModule ); 122 | 123 | /** 124 | * Gets a module from a script function. 125 | * @param pFunction Script function to retrieve the module from. 126 | * @return The module, or null if it couldn't be retrieved. 127 | */ 128 | CASModule* GetModuleFromScriptFunction( const asIScriptFunction* pFunction ); 129 | 130 | /** 131 | * Gets a module from a script context. 132 | * @param pContext Script context to retrieve the module from. Uses the function currently being executed. 133 | * @return The module, or null if it couldn't be retrieved. 134 | */ 135 | CASModule* GetModuleFromScriptContext( asIScriptContext* pContext ); 136 | 137 | /** 138 | * Gets a script module from a script context. 139 | * @param pContext Script context to retrieve the module from. Uses the function currently being executed. 140 | * @return The script module, or null if it couldn't be retrieved. 141 | */ 142 | asIScriptModule* GetScriptModuleFromScriptContext( asIScriptContext* pContext ); 143 | 144 | /** 145 | * Less function for modules. 146 | * @param pLHS Left hand module. 147 | * @param pRHS Right hand module. 148 | * @return true if the left hand module is smaller than the right hand module. 149 | */ 150 | inline bool ModuleLess( const CASModule* pLHS, const CASModule* pRHS ) 151 | { 152 | if( pLHS->GetDescriptor() < pRHS->GetDescriptor() ) 153 | return true; 154 | 155 | if( pRHS->GetDescriptor() < pLHS->GetDescriptor() ) 156 | return false; 157 | 158 | //Use the memory address for sorting. They need only be sorted in a unique order. 159 | return pLHS < pRHS; 160 | } 161 | 162 | /** 163 | * Functor that overloads operator() to return true if a module equals a given name. 164 | */ 165 | struct ModuleEqualByName final 166 | { 167 | const char* const pszModuleName; 168 | 169 | ModuleEqualByName( const char* const pszModuleName ) 170 | : pszModuleName( pszModuleName ) 171 | { 172 | } 173 | 174 | ModuleEqualByName( const ModuleEqualByName& other ) = default; 175 | 176 | bool operator()( const CASModule* pModule ) const 177 | { 178 | return strcmp( pModule->GetModuleName(), pszModuleName ) == 0; 179 | } 180 | 181 | private: 182 | ModuleEqualByName& operator=( const ModuleEqualByName& ) = delete; 183 | }; 184 | 185 | /** @} */ 186 | 187 | #endif //ANGELSCRIPT_CASMODULE_H -------------------------------------------------------------------------------- /src/AngelscriptUtils/CASModuleDescriptor.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "CASModuleDescriptor.h" 4 | 5 | CASModuleDescriptor::CASModuleDescriptor( const char* const pszName, const asDWORD accessMask, const as::ModulePriority_t priority, const as::DescriptorID_t descriptorID ) 6 | : m_pszName( pszName ) 7 | , m_AccessMask( accessMask ) 8 | , m_Priority( priority ) 9 | , m_DescriptorID( descriptorID ) 10 | { 11 | assert( pszName ); 12 | assert( pszName && *pszName ); 13 | //A module with no access to anything is rather useless. 14 | assert( accessMask != 0 ); 15 | assert( descriptorID != as::INVALID_DESCRIPTOR_ID ); 16 | } -------------------------------------------------------------------------------- /src/AngelscriptUtils/CASModuleDescriptor.h: -------------------------------------------------------------------------------- 1 | #ifndef ANGELSCRIPT_CASMODULEDESCRIPTOR_H 2 | #define ANGELSCRIPT_CASMODULEDESCRIPTOR_H 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | /** 10 | * @addtogroup ASModule 11 | * 12 | * @{ 13 | */ 14 | 15 | namespace as 16 | { 17 | typedef int32_t ModulePriority_t; 18 | 19 | namespace ModulePriority 20 | { 21 | /** 22 | * Predefined priority levels for modules. 23 | */ 24 | enum ModulePriority : ModulePriority_t 25 | { 26 | NORMAL = 0, 27 | HIGH = INT32_MAX / 2, 28 | HIGHEST = INT32_MAX, 29 | LOW = INT32_MIN / 2, 30 | LOWEST = INT32_MIN 31 | }; 32 | } 33 | 34 | typedef uint32_t DescriptorID_t; 35 | 36 | const DescriptorID_t INVALID_DESCRIPTOR_ID = 0; 37 | 38 | const DescriptorID_t FIRST_DESCRIPTOR_ID = 1; 39 | 40 | const DescriptorID_t LAST_DESCRIPTOR_ID = UINT32_MAX; 41 | } 42 | 43 | /** 44 | * Describes a module. This includes its name, access mask, and priority in event/function call execution. 45 | */ 46 | class CASModuleDescriptor final 47 | { 48 | public: 49 | /** 50 | * Constructor. 51 | * @param pszName Name of the module descriptor. 52 | * @param accessMask Access mask. 53 | * @param priority Event/function call execution priority. 54 | * @param descriptorID ID assigned to this descriptor. 55 | */ 56 | CASModuleDescriptor( const char* const pszName, const asDWORD accessMask, const as::ModulePriority_t priority, const as::DescriptorID_t descriptorID ); 57 | 58 | const char* GetName() const { return m_pszName; } 59 | 60 | asDWORD GetAccessMask() const { return m_AccessMask; } 61 | 62 | as::ModulePriority_t GetPriority() const { return m_Priority; } 63 | 64 | as::DescriptorID_t GetDescriptorID() const { return m_DescriptorID; } 65 | 66 | private: 67 | const char* const m_pszName; 68 | 69 | const asDWORD m_AccessMask; 70 | 71 | const as::ModulePriority_t m_Priority; 72 | 73 | const as::DescriptorID_t m_DescriptorID; 74 | 75 | private: 76 | CASModuleDescriptor( const CASModuleDescriptor& ) = delete; 77 | CASModuleDescriptor& operator=( const CASModuleDescriptor& ) = delete; 78 | }; 79 | 80 | /** 81 | * Equality operator for descriptors. 82 | * @param lhs Left hand descriptor. 83 | * @param rhs Right hand descriptor. 84 | * @return true if they are equal, false otherwise. 85 | */ 86 | inline bool operator==( const CASModuleDescriptor& lhs, const CASModuleDescriptor& rhs ) 87 | { 88 | //Since each descriptor has a unique name, they can only be equal if they are the same object. 89 | return &lhs == &rhs; 90 | } 91 | 92 | /** 93 | * Inequality operator for descriptors. 94 | * @param lhs Left hand descriptor. 95 | * @param rhs Right hand descriptor. 96 | * @return true if they are not equal, false otherwise. 97 | */ 98 | inline bool operator!=( const CASModuleDescriptor& lhs, const CASModuleDescriptor& rhs ) 99 | { 100 | return !( lhs == rhs ); 101 | } 102 | 103 | /** 104 | * Operator less than for descriptors. 105 | * @param lhs Left hand descriptor. 106 | * @param rhs Right hand descriptor. 107 | * @return true if the left hand descriptor is smaller than the right hand descriptor. 108 | */ 109 | inline bool operator<( const CASModuleDescriptor& lhs, const CASModuleDescriptor& rhs ) 110 | { 111 | //Both are invalid; lhs is smaller. 112 | if( lhs.GetDescriptorID() == as::INVALID_DESCRIPTOR_ID && rhs.GetDescriptorID() == as::INVALID_DESCRIPTOR_ID ) 113 | return true; 114 | 115 | //lhs is invalid, always greater. 116 | if( lhs.GetDescriptorID() == as::INVALID_DESCRIPTOR_ID && rhs.GetDescriptorID() != as::INVALID_DESCRIPTOR_ID ) 117 | return false; 118 | 119 | //rhs is invalid, always smaller. 120 | if( lhs.GetDescriptorID() != as::INVALID_DESCRIPTOR_ID && rhs.GetDescriptorID() == as::INVALID_DESCRIPTOR_ID ) 121 | return true; 122 | 123 | //Higher priority, smaller. 124 | if( lhs.GetPriority() > rhs.GetPriority() ) 125 | return true; 126 | 127 | //Lower priority, greater. 128 | if( lhs.GetPriority() < rhs.GetPriority() ) 129 | return false; 130 | 131 | //Same priority, smaller module ID is smaller. 132 | return lhs.GetDescriptorID() < rhs.GetDescriptorID(); 133 | } 134 | 135 | namespace std 136 | { 137 | template<> 138 | struct less 139 | { 140 | typedef CASModuleDescriptor first_argument_type; 141 | typedef CASModuleDescriptor second_argument_type; 142 | typedef bool result_type; 143 | 144 | bool operator()( const CASModuleDescriptor& lhs, const CASModuleDescriptor& rhs ) const 145 | { 146 | return lhs < rhs; 147 | } 148 | }; 149 | } 150 | 151 | /** @} */ 152 | 153 | #endif //ANGELSCRIPT_CASMODULEDESCRIPTOR_H -------------------------------------------------------------------------------- /src/AngelscriptUtils/CASModuleManager.h: -------------------------------------------------------------------------------- 1 | #ifndef ANGELSCRIPT_CASMODULEMANAGER_H 2 | #define ANGELSCRIPT_CASMODULEMANAGER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | #include "util/StringUtils.h" 12 | 13 | #include "CASModuleDescriptor.h" 14 | 15 | class CASEventManager; 16 | class CASModule; 17 | class IASModuleBuilder; 18 | class IASModuleUserData; 19 | 20 | /** 21 | * @addtogroup ASModule 22 | * 23 | * @{ 24 | */ 25 | 26 | /** 27 | * Manages a list of module descriptors and modules. 28 | */ 29 | class CASModuleManager final 30 | { 31 | private: 32 | typedef std::unordered_map, as::Hash_C_String, as::EqualTo_C_String> Descriptors_t; 33 | typedef std::vector Modules_t; 34 | 35 | public: 36 | /** 37 | * Constructor. 38 | * @param engine Script engine. 39 | * @param eventManager Optional. The event manager that manages the global events that modules use. 40 | */ 41 | CASModuleManager( asIScriptEngine& engine, const std::shared_ptr& eventManager = nullptr ); 42 | 43 | /** 44 | * Destructor. 45 | */ 46 | ~CASModuleManager(); 47 | 48 | /** 49 | * @return The script engine. 50 | */ 51 | asIScriptEngine& GetEngine() { return m_Engine; } 52 | 53 | /** 54 | * @return The event manager, if this manager has one. 55 | */ 56 | CASEventManager* GetEventManager() { return m_EventManager.get(); } 57 | 58 | /** 59 | * Finds a descriptor by name. 60 | * @param pszName Name of the descriptor. Case sensitive. 61 | * @return Descriptor, or null if it couldn't be found. 62 | */ 63 | const CASModuleDescriptor* FindDescriptorByName( const char* const pszName ) const; 64 | 65 | /** 66 | * Adds a new descriptor. 67 | * @param pszName Name of the descriptor. Must be unique. 68 | * @param accessMask Access mask. 69 | * @param priority Priority. 70 | * @return Pair containing the descriptor and whether the descriptor was added in this call. If the descriptor already existed, first contains that descriptor and second is set to false. 71 | * @see CASModuleDescriptor 72 | */ 73 | std::pair AddDescriptor( const char* const pszName, const asDWORD accessMask, const as::ModulePriority_t priority = as::ModulePriority::NORMAL ); 74 | 75 | /** 76 | * Builds a module using the given descriptor. 77 | * @param descriptor Descriptor to use. 78 | * @param pszModuleName Name of the module. Must be unique. 79 | * @param builder Builder to use. 80 | * @param pUserData Optional. User data to associate with the module. Will be released if the module failed to build. 81 | * @return On successful build, the module. Otherwise, null. 82 | */ 83 | CASModule* BuildModule( const CASModuleDescriptor& descriptor, const char* const pszModuleName, IASModuleBuilder& builder, IASModuleUserData* pUserData = nullptr ); 84 | 85 | /** 86 | * Builds a module using the given descriptor. 87 | * @param pszName Name of the descriptor to use. 88 | * @param pszModuleName Name of the module. Must be unique. 89 | * @param builder Builder to use. 90 | * @param pUserData Optional. User data to associate with the module. Will be released if the module failed to build. 91 | * @return On successful build, the module. Otherwise, null. 92 | */ 93 | CASModule* BuildModule( const char* const pszName, const char* const pszModuleName, IASModuleBuilder& builder, IASModuleUserData* pUserData = nullptr ); 94 | 95 | private: 96 | /** 97 | * Builds a module using the given descriptor. 98 | * @param descriptor Descriptor to use. 99 | * @param pszModuleName Name of the module. Must be unique. 100 | * @param builder Builder to use. 101 | * @param pUserData Optional. User data to associate with the module. Will be released if the module failed to build. 102 | * @return On successful build, the module. Otherwise, null. 103 | */ 104 | CASModule* BuildModuleInternal( const CASModuleDescriptor& descriptor, const char* const pszModuleName, IASModuleBuilder& builder, IASModuleUserData* pUserData = nullptr ); 105 | 106 | public: 107 | /** 108 | * @return The number of modules that are currently loaded. 109 | */ 110 | size_t GetModuleCount() const; 111 | 112 | /** 113 | * Finds a module by name. 114 | * @param pszModuleName Name of the module. Case sensitive. 115 | * @return Module, or null if the module couldn't be found. 116 | */ 117 | const CASModule* FindModuleByName( const char* const pszModuleName ) const; 118 | 119 | /** 120 | * @copydoc FindModuleByName( const char* const pszModuleName ) const 121 | */ 122 | CASModule* FindModuleByName( const char* const pszModuleName ); 123 | 124 | /** 125 | * Finds a module by index. 126 | * @param uiIndex Index of the module. 127 | * @return Module, or null if the module couldn't be found. 128 | */ 129 | const CASModule* FindModuleByIndex( const size_t uiIndex ) const; 130 | 131 | /** 132 | * @copydoc FindModuleByIndex( const size_t uiIndex ) const 133 | */ 134 | CASModule* FindModuleByIndex( const size_t uiIndex ); 135 | 136 | private: 137 | /** 138 | * Adds a module. 139 | * @param pModule Module to add. 140 | * @return true if the module was added, false otherwise. 141 | */ 142 | bool AddModule( CASModule* pModule ); 143 | 144 | public: 145 | /** 146 | * Removes a module. The module may not be destroyed immediately if there are active references held to it. 147 | * @param pModule Module to remove. 148 | */ 149 | void RemoveModule( CASModule* pModule ); 150 | 151 | /** 152 | * @see RemoveModule( CASModule* pModule ) 153 | * @param pszModuleName Name of the module. Case sensitive. 154 | */ 155 | void RemoveModule( const char* const pszModuleName ); 156 | 157 | /** 158 | * Removes all modules and descriptors. 159 | */ 160 | void Clear(); 161 | 162 | private: 163 | asIScriptEngine& m_Engine; 164 | 165 | std::shared_ptr m_EventManager; 166 | 167 | Descriptors_t m_Descriptors; 168 | 169 | as::DescriptorID_t m_NextDescriptorID = as::FIRST_DESCRIPTOR_ID; 170 | 171 | Modules_t m_Modules; 172 | 173 | private: 174 | CASModuleManager( const CASModuleManager& ) = delete; 175 | CASModuleManager& operator=( const CASModuleManager& ) = delete; 176 | }; 177 | 178 | /** @} */ 179 | 180 | #endif //ANGELSCRIPT_CASMODULEMANAGER_H -------------------------------------------------------------------------------- /src/AngelscriptUtils/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # AngelscriptUtils library 3 | # 4 | 5 | set( TARGET_NAME AngelscriptUtils ) 6 | 7 | set( ANGELSCRIPTUTILS_VERSION_MAJOR 0 ) 8 | set( ANGELSCRIPTUTILS_VERSION_MINOR 1 ) 9 | set( ANGELSCRIPTUTILS_VERSION_PATCH 0 ) 10 | set( PROJECT_VERSION ${ANGELSCRIPTUTILS_VERSION_MAJOR}.${ANGELSCRIPTUTILS_VERSION_MINOR}.${ANGELSCRIPTUTILS_VERSION_PATCH} ) 11 | 12 | find_package( Threads REQUIRED ) 13 | find_package( spdlog CONFIG REQUIRED ) 14 | find_package( Angelscript CONFIG 2.32.0 REQUIRED ) 15 | 16 | set( ASUTILS_CASMODULE_USER_DATA_ID "10001" CACHE STRING "Value for the CASModule user data ID" ) 17 | set( ASUTILS_CONTEXT_RESULTHANDLER_USERDATA_ID "20001" CACHE STRING "Value for the context result handler user data ID" ) 18 | 19 | configure_file( 20 | ${CMAKE_CURRENT_SOURCE_DIR}/ASUtilsConfig.h.in 21 | ${CMAKE_CURRENT_SOURCE_DIR}/ASUtilsConfig.h 22 | @ONLY 23 | ) 24 | 25 | add_sources( 26 | ASUtilsConfig.h 27 | CASLoggingContextResultHandler.cpp 28 | CASLoggingContextResultHandler.h 29 | CASManager.cpp 30 | CASManager.h 31 | CASModuleDescriptor.cpp 32 | CASModuleDescriptor.h 33 | CASModule.cpp 34 | CASModule.h 35 | CASModuleManager.cpp 36 | CASModuleManager.h 37 | IASContextResultHandler.h 38 | IASInitializer.h 39 | IASModuleBuilder.h 40 | add_on/scriptbuilder/scriptbuilder.cpp 41 | add_on/scriptbuilder/scriptbuilder.h 42 | ) 43 | 44 | add_includes( 45 | ASUtilsConfig.h 46 | CASLoggingContextResultHandler.h 47 | CASManager.h 48 | CASModuleDescriptor.h 49 | CASModule.h 50 | CASModuleManager.h 51 | IASContextResultHandler.h 52 | IASInitializer.h 53 | IASModuleBuilder.h 54 | std_make_unique.h 55 | add_on/scriptbuilder/scriptbuilder.h 56 | ) 57 | 58 | add_subdirectory( event ) 59 | add_subdirectory( ScriptAPI ) 60 | add_subdirectory( util ) 61 | add_subdirectory( wrapper ) 62 | 63 | preprocess_sources() 64 | 65 | add_library( ${TARGET_NAME} STATIC ${PREP_SRCS} ) 66 | 67 | check_winxp_support( ${TARGET_NAME} ) 68 | 69 | configure_msvc_runtime( ${TARGET_NAME} ${MSVC_RUNTIME_CONFIG} ) 70 | 71 | target_include_directories( ${TARGET_NAME} PRIVATE 72 | ${SRC_DIR} 73 | ) 74 | 75 | target_compile_definitions( ${TARGET_NAME} PRIVATE 76 | ${SHARED_DEFS} 77 | ) 78 | 79 | target_link_libraries( ${TARGET_NAME} 80 | Angelscript::angelscript 81 | spdlog::spdlog 82 | ) 83 | 84 | set_target_properties( ${TARGET_NAME} PROPERTIES 85 | COMPILE_FLAGS "${SHARED_COMPILE_FLAGS}" 86 | LINK_FLAGS "${SHARED_LINK_FLAGS}" 87 | ) 88 | 89 | set_pdb_names( ${TARGET_NAME} ) 90 | 91 | #Create filters 92 | create_source_groups( "${SRC_DIR}" ) 93 | 94 | install_pdbs( ${TARGET_NAME} lib ) 95 | install_includes( "${SRC_DIR}" COMPONENT Devel ) 96 | 97 | #See https://cmake.org/cmake/help/latest/manual/cmake-packages.7.html#creating-packages for a detailed explanation about this part 98 | install( TARGETS ${TARGET_NAME} EXPORT AngelscriptUtilsTargets 99 | RUNTIME DESTINATION bin 100 | LIBRARY DESTINATION lib 101 | ARCHIVE DESTINATION lib 102 | INCLUDES DESTINATION include 103 | ) 104 | 105 | include( CMakePackageConfigHelpers ) 106 | write_basic_package_version_file( 107 | "${CMAKE_CURRENT_BINARY_DIR}/AngelscriptUtils/AngelscriptUtilsConfigVersion.cmake" 108 | VERSION ${PROJECT_VERSION} 109 | COMPATIBILITY AnyNewerVersion 110 | ) 111 | 112 | export( EXPORT AngelscriptUtilsTargets 113 | FILE "${CMAKE_CURRENT_BINARY_DIR}/AngelscriptUtils/AngelscriptUtilsTargets.cmake" 114 | NAMESPACE AngelscriptUtils:: 115 | ) 116 | configure_file( cmake/AngelscriptUtilsConfig.cmake 117 | "${CMAKE_CURRENT_BINARY_DIR}/AngelscriptUtils/AngelscriptUtilsConfig.cmake" 118 | COPYONLY 119 | ) 120 | 121 | set( ConfigPackageLocation lib/cmake/AngelscriptUtils) 122 | install( EXPORT AngelscriptUtilsTargets 123 | FILE AngelscriptUtilsTargets.cmake 124 | NAMESPACE AngelscriptUtils:: 125 | DESTINATION ${ConfigPackageLocation} 126 | ) 127 | install( 128 | FILES 129 | cmake/AngelscriptUtilsConfig.cmake 130 | "${CMAKE_CURRENT_BINARY_DIR}/AngelscriptUtils/AngelscriptUtilsConfigVersion.cmake" 131 | DESTINATION ${ConfigPackageLocation} 132 | COMPONENT Devel 133 | ) 134 | 135 | clear_sources() 136 | -------------------------------------------------------------------------------- /src/AngelscriptUtils/IASContextResultHandler.h: -------------------------------------------------------------------------------- 1 | #ifndef ANGELSCRIPT_IASCONTEXTRESULTHANDLER_H 2 | #define ANGELSCRIPT_IASCONTEXTRESULTHANDLER_H 3 | 4 | #include 5 | 6 | #include "ASUtilsConfig.h" 7 | 8 | #include "util/ASPlatform.h" 9 | 10 | /** 11 | * Provides result handling functions for context operations. 12 | * Is reference counted. 13 | */ 14 | class IASContextResultHandler 15 | { 16 | public: 17 | virtual ~IASContextResultHandler() = 0; 18 | 19 | virtual void AddRef() const = 0; 20 | 21 | virtual void Release() const = 0; 22 | 23 | /** 24 | * Processes the asIScriptContext::Prepare return value. 25 | * @param function Function that was prepared for execution. 26 | * @param context Context that was prepared. 27 | * @param iResult Result code. 28 | */ 29 | virtual void ProcessPrepareResult( asIScriptFunction& function, asIScriptContext& context, int iResult ); 30 | 31 | /** 32 | * Processes the asIScriptContext::Execute return value. 33 | * @param function Function that was executed. 34 | * @param context Context that was used to execute the function. 35 | * @param iResult Result code. 36 | */ 37 | virtual void ProcessExecuteResult( asIScriptFunction& function, asIScriptContext& context, int iResult ); 38 | 39 | /** 40 | * Processes the asIScriptContext::Unprepare return value. 41 | * @param context Context that was unprepared. 42 | * @param iResult Result code. 43 | */ 44 | virtual void ProcessUnprepareResult( asIScriptContext& context, int iResult ); 45 | }; 46 | 47 | inline IASContextResultHandler::~IASContextResultHandler() 48 | { 49 | } 50 | 51 | inline void IASContextResultHandler::ProcessPrepareResult( asIScriptFunction&, asIScriptContext&, int ) 52 | { 53 | } 54 | 55 | inline void IASContextResultHandler::ProcessExecuteResult( asIScriptFunction&, asIScriptContext&, int ) 56 | { 57 | } 58 | 59 | inline void IASContextResultHandler::ProcessUnprepareResult( asIScriptContext&, int ) 60 | { 61 | } 62 | 63 | namespace as 64 | { 65 | /** 66 | * Gets the result handler from the given context. 67 | * Does not increment the reference count for the returned handler. 68 | * @return If the context has a result handler, returns the handler. Otherwise, returns null. 69 | */ 70 | inline IASContextResultHandler* GetContextResultHandler( const asIScriptContext& context ) 71 | { 72 | return reinterpret_cast( context.GetUserData( ASUTILS_CONTEXT_RESULTHANDLER_USERDATA_ID ) ); 73 | } 74 | 75 | /** 76 | * Sets the result handler for the given context. 77 | * @param context Context to set the handler on. 78 | * @param pHandler Handler to set. Can be null. 79 | */ 80 | inline void SetContextResultHandler( asIScriptContext& context, IASContextResultHandler* pHandler ) 81 | { 82 | //AddRef the new one first in case it's the same handler that was already present. 83 | //This prevents the ref count from dropping to 0 unexpectedly. 84 | if( pHandler ) 85 | pHandler->AddRef(); 86 | 87 | auto pOldHandler = reinterpret_cast( context.SetUserData( pHandler, ASUTILS_CONTEXT_RESULTHANDLER_USERDATA_ID ) ); 88 | 89 | if( pOldHandler ) 90 | pOldHandler->Release(); 91 | } 92 | 93 | /** 94 | * Callback used to free the context result handler. 95 | * Set this after creating the engine. 96 | */ 97 | inline void FreeContextResultHandler( asIScriptContext* pContext ) 98 | { 99 | as::SetContextResultHandler( *pContext, nullptr ); 100 | } 101 | } 102 | 103 | #endif //ANGELSCRIPT_IASCONTEXTRESULTHANDLER_H 104 | -------------------------------------------------------------------------------- /src/AngelscriptUtils/IASInitializer.h: -------------------------------------------------------------------------------- 1 | #ifndef ANGELSCRIPT_IASINITIALIZER_H 2 | #define ANGELSCRIPT_IASINITIALIZER_H 3 | 4 | #include 5 | 6 | #include "util/ASPlatform.h" 7 | 8 | /** 9 | * @addtogroup ASManager 10 | * 11 | * @{ 12 | */ 13 | 14 | class CASManager; 15 | class CASEventManager; 16 | 17 | /** 18 | * Used by the manager to initialize itself. 19 | */ 20 | class IASInitializer 21 | { 22 | public: 23 | virtual ~IASInitializer() = 0; 24 | 25 | /** 26 | * Called when initialization has started. 27 | */ 28 | virtual void OnInitBegin() {} 29 | 30 | /** 31 | * Called when initialization has ended. 32 | * @param bSuccess Whether initialization succeeded. 33 | */ 34 | virtual void OnInitEnd( const bool bSuccess ); 35 | 36 | /** 37 | * Allows applications to provide a message callback to be installed upon initialization. 38 | * @param[ out ] outFuncPtr Function to use. 39 | * @param[ out ] pOutObj Object to use. 40 | * @param[ out ] outCallConv Calling convention. 41 | * @return true if a callback was set, false otherwise. 42 | */ 43 | virtual bool GetMessageCallback( asSFuncPtr& outFuncPtr, void*& pOutObj, asDWORD& outCallConv ); 44 | 45 | /** 46 | * @return Whether to create an event manager. 47 | */ 48 | virtual bool UseEventManager() { return false; } 49 | 50 | /** 51 | * Gets the namespace in which events should be registered. Default "Events". 52 | */ 53 | virtual const char* GetEventNamespace() { return "Events"; } 54 | 55 | /** 56 | * Should register the core API, including the following types: 57 | * string 58 | * dictionary 59 | * array 60 | * @param manager Manager. 61 | * @return true on success, false otherwise. 62 | */ 63 | virtual bool RegisterCoreAPI( CASManager& manager ) = 0; 64 | 65 | /** 66 | * Should register events. 67 | * @param manager Manager. 68 | * @param eventManager Event manager. 69 | * @return true on success, false otherwise. 70 | */ 71 | virtual bool AddEvents( CASManager& manager, CASEventManager& eventManager ); 72 | 73 | /** 74 | * Should register the remainder of the API. 75 | * @param manager Manager. 76 | * @return true on success, false otherwise. 77 | */ 78 | virtual bool RegisterAPI( CASManager& manager ) = 0; 79 | }; 80 | 81 | inline IASInitializer::~IASInitializer() 82 | { 83 | } 84 | 85 | inline void IASInitializer::OnInitEnd( const bool ) 86 | { 87 | } 88 | 89 | inline bool IASInitializer::GetMessageCallback( asSFuncPtr&, void*&, asDWORD& ) 90 | { 91 | return false; 92 | } 93 | 94 | inline bool IASInitializer::AddEvents( CASManager&, CASEventManager& ) 95 | { 96 | return true; 97 | } 98 | 99 | /** @} */ 100 | 101 | #endif //ANGELSCRIPT_IASINITIALIZER_H -------------------------------------------------------------------------------- /src/AngelscriptUtils/IASModuleBuilder.h: -------------------------------------------------------------------------------- 1 | #ifndef ANGELSCRIPT_IASMODULEBUILDER_H 2 | #define ANGELSCRIPT_IASMODULEBUILDER_H 3 | 4 | #include "util/ASPlatform.h" 5 | 6 | class CScriptBuilder; 7 | class CASModule; 8 | 9 | /** 10 | * @addtogroup ASModule 11 | * 12 | * @{ 13 | */ 14 | 15 | /** 16 | * Interface used to provide necessary information to build a module. 17 | */ 18 | class IASModuleBuilder 19 | { 20 | public: 21 | /** 22 | * Destructor. 23 | */ 24 | virtual ~IASModuleBuilder() = 0; 25 | 26 | /** 27 | * Allows preprocessor words to be defined. 28 | * @param builder Builder to define words for. 29 | * @return true on success, false on failure. 30 | */ 31 | virtual bool DefineWords( CScriptBuilder& builder ); 32 | 33 | /** 34 | * Allows scripts to be added. 35 | * @param builder Builder to add scripts to. 36 | * @return true on success, false on failure. 37 | */ 38 | virtual bool AddScripts( CScriptBuilder& builder ) = 0; 39 | 40 | /** 41 | * Allows \#include statements to be processed. 42 | * @param builder Builder to add scripts to. 43 | * @param pszIncludeFileName Name of the file that is being included. 44 | * @param pszFromFileName Name of the file that contains the include statement. 45 | * @return true on success, false on failure. 46 | */ 47 | virtual bool IncludeScript( CScriptBuilder& builder, 48 | const char* const pszIncludeFileName, 49 | const char* const pszFromFileName ); 50 | 51 | /** 52 | * Called right before the module is built. Gives the builder a chance to evaluate the module. 53 | * @param builder Builder. 54 | * @return true if the module should be built, false otherwise. 55 | */ 56 | virtual bool PreBuild( CScriptBuilder& builder ); 57 | 58 | /** 59 | * Called after the build has finished. 60 | * @param builder Builder. 61 | * @param bSuccess Whether the build succeeded or failed. 62 | * @param pModule If bSuccess is true, the module. Otherwise, null. 63 | * @return true if the module should be kept, false if it should be discarded. 64 | */ 65 | virtual bool PostBuild( CScriptBuilder& builder, const bool bSuccess, CASModule* pModule ); 66 | }; 67 | 68 | inline IASModuleBuilder::~IASModuleBuilder() 69 | { 70 | } 71 | 72 | inline bool IASModuleBuilder::DefineWords( CScriptBuilder& ) 73 | { 74 | return true; 75 | } 76 | 77 | inline bool IASModuleBuilder::IncludeScript( CScriptBuilder&, const char* const, const char* const ) 78 | { 79 | return false; 80 | } 81 | 82 | inline bool IASModuleBuilder::PreBuild( CScriptBuilder& ) 83 | { 84 | return true; 85 | } 86 | 87 | inline bool IASModuleBuilder::PostBuild( CScriptBuilder&, const bool, CASModule* ) 88 | { 89 | return true; 90 | } 91 | 92 | /** @} */ 93 | 94 | #endif //ANGELSCRIPT_IASMODULEBUILDER_H -------------------------------------------------------------------------------- /src/AngelscriptUtils/ScriptAPI/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_sources( 2 | CASScheduler.h 3 | CASScheduler.cpp 4 | ) 5 | 6 | add_includes( 7 | CASScheduler.h 8 | ) 9 | 10 | add_subdirectory( Reflection ) -------------------------------------------------------------------------------- /src/AngelscriptUtils/ScriptAPI/Reflection/ASReflection.h: -------------------------------------------------------------------------------- 1 | #ifndef ANGELSCRIPT_SCRIPTAPI_REFLECTION_ASREFLECTION_H 2 | #define ANGELSCRIPT_SCRIPTAPI_REFLECTION_ASREFLECTION_H 3 | 4 | class asIScriptEngine; 5 | 6 | void RegisterScriptReflection( asIScriptEngine& engine ); 7 | 8 | #endif //ANGELSCRIPT_SCRIPTAPI_REFLECTION_ASREFLECTION_H -------------------------------------------------------------------------------- /src/AngelscriptUtils/ScriptAPI/Reflection/CASEngineReflectionGroup.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "AngelscriptUtils/util/ASUtil.h" 4 | 5 | #include "CASEngineReflectionGroup.h" 6 | 7 | asIScriptFunction* CASEngineReflectionGroup::FindGlobalFunction( const std::string& szName, bool bSearchByDecl ) 8 | { 9 | assert( m_pEngine ); 10 | 11 | asIScriptFunction* pFunction = nullptr; 12 | 13 | if( bSearchByDecl ) 14 | { 15 | const std::string szOldNS = m_pEngine->GetDefaultNamespace(); 16 | 17 | const std::string szNS = as::ExtractNamespaceFromDecl( szName ); 18 | 19 | m_pEngine->SetDefaultNamespace( szNS.c_str() ); 20 | 21 | pFunction = m_pEngine->GetGlobalFunctionByDecl( szName.c_str() ); 22 | 23 | m_pEngine->SetDefaultNamespace( szOldNS.c_str() ); 24 | } 25 | else 26 | { 27 | const std::string szNS = as::ExtractNamespaceFromName( szName ); 28 | const std::string szActualName = as::ExtractNameFromName( szName ); 29 | 30 | const asUINT uiCount = m_pEngine->GetGlobalFunctionCount(); 31 | 32 | for( asUINT uiIndex = 0; uiIndex < uiCount; ++uiIndex ) 33 | { 34 | auto pFunc = m_pEngine->GetGlobalFunctionByIndex( uiIndex ); 35 | 36 | if( szActualName == pFunc->GetName() && szNS == pFunc->GetNamespace() ) 37 | { 38 | pFunction = pFunc; 39 | break; 40 | } 41 | } 42 | } 43 | 44 | if( pFunction ) 45 | pFunction->AddRef(); 46 | 47 | return pFunction; 48 | } 49 | 50 | asUINT CASEngineReflectionGroup::GetGlobalFunctionCount() const 51 | { 52 | assert( m_pEngine ); 53 | 54 | return m_pEngine->GetGlobalFunctionCount(); 55 | } 56 | 57 | asIScriptFunction* CASEngineReflectionGroup::GetGlobalFunctionByIndex( asUINT uiIndex ) 58 | { 59 | assert( m_pEngine ); 60 | 61 | if( auto pFunction = m_pEngine->GetGlobalFunctionByIndex( uiIndex ) ) 62 | { 63 | pFunction->AddRef(); 64 | return pFunction; 65 | } 66 | 67 | return nullptr; 68 | } 69 | 70 | asITypeInfo* CASEngineReflectionGroup::FindTypeInfo( const std::string& szName, bool bSearchByDecl ) 71 | { 72 | assert( m_pEngine ); 73 | 74 | const std::string szOldNS = m_pEngine->GetDefaultNamespace(); 75 | 76 | asITypeInfo* pType; 77 | 78 | if( bSearchByDecl ) 79 | { 80 | const std::string szNS = as::ExtractNamespaceFromDecl( szName, false ); 81 | 82 | m_pEngine->SetDefaultNamespace( szNS.c_str() ); 83 | 84 | pType = m_pEngine->GetTypeInfoByDecl( szName.c_str() ); 85 | } 86 | else 87 | { 88 | const std::string szNS = as::ExtractNamespaceFromName( szName ); 89 | const std::string szActualName = as::ExtractNameFromName( szName ); 90 | 91 | m_pEngine->SetDefaultNamespace( szNS.c_str() ); 92 | 93 | pType = m_pEngine->GetTypeInfoByName( szActualName.c_str() ); 94 | } 95 | 96 | m_pEngine->SetDefaultNamespace( szOldNS.c_str() ); 97 | 98 | if( pType ) 99 | pType->AddRef(); 100 | 101 | return pType; 102 | } 103 | 104 | asUINT CASEngineReflectionGroup::GetObjectTypeCount() const 105 | { 106 | assert( m_pEngine ); 107 | 108 | return m_pEngine->GetObjectTypeCount(); 109 | } 110 | 111 | asITypeInfo* CASEngineReflectionGroup::GetObjectTypeByIndex( asUINT uiIndex ) 112 | { 113 | assert( m_pEngine ); 114 | 115 | if( auto pType = m_pEngine->GetObjectTypeByIndex( uiIndex ) ) 116 | { 117 | pType->AddRef(); 118 | return pType; 119 | } 120 | 121 | return nullptr; 122 | } -------------------------------------------------------------------------------- /src/AngelscriptUtils/ScriptAPI/Reflection/CASEngineReflectionGroup.h: -------------------------------------------------------------------------------- 1 | #ifndef ANGELSCRIPT_SCRIPTAPI_REFLECTION_CASENGINEREFLECTIONGROUP_H 2 | #define ANGELSCRIPT_SCRIPTAPI_REFLECTION_CASENGINEREFLECTIONGROUP_H 3 | 4 | #include "IASReflectionGroup.h" 5 | 6 | class CASEngineReflectionGroup : public IASReflectionGroup 7 | { 8 | public: 9 | CASEngineReflectionGroup() = default; 10 | ~CASEngineReflectionGroup() = default; 11 | 12 | asIScriptFunction* FindGlobalFunction( const std::string& szName, bool bSearchByDecl = false ) override; 13 | 14 | asUINT GetGlobalFunctionCount() const override; 15 | 16 | asIScriptFunction* GetGlobalFunctionByIndex( asUINT uiIndex ) override; 17 | 18 | asITypeInfo* FindTypeInfo( const std::string& szName, bool bSearchByDecl = false ) override; 19 | 20 | asUINT GetObjectTypeCount() const override; 21 | 22 | asITypeInfo* GetObjectTypeByIndex( asUINT uiIndex ) override; 23 | 24 | void SetEngine( asIScriptEngine& engine ) 25 | { 26 | m_pEngine = &engine; 27 | } 28 | 29 | private: 30 | asIScriptEngine* m_pEngine = nullptr; 31 | 32 | private: 33 | CASEngineReflectionGroup( const CASEngineReflectionGroup& ) = delete; 34 | CASEngineReflectionGroup& operator=( const CASEngineReflectionGroup& ) = delete; 35 | }; 36 | 37 | #endif //ANGELSCRIPT_SCRIPTAPI_REFLECTION_CASENGINEREFLECTIONGROUP_H -------------------------------------------------------------------------------- /src/AngelscriptUtils/ScriptAPI/Reflection/CASModuleReflectionGroup.cpp: -------------------------------------------------------------------------------- 1 | #include "AngelscriptUtils/CASModule.h" 2 | 3 | #include "AngelscriptUtils/util/ASUtil.h" 4 | 5 | #include "CASModuleReflectionGroup.h" 6 | 7 | asIScriptFunction* CASModuleReflectionGroup::FindGlobalFunction( const std::string& szName, bool bSearchByDecl ) 8 | { 9 | auto& scriptModule = *GetScriptModuleFromScriptContext( asGetActiveContext() ); 10 | 11 | asIScriptFunction* pFunction = nullptr; 12 | 13 | if( bSearchByDecl ) 14 | { 15 | const std::string szOldNS = scriptModule.GetDefaultNamespace(); 16 | 17 | const std::string szNS = as::ExtractNamespaceFromDecl( szName ); 18 | 19 | scriptModule.SetDefaultNamespace( szNS.c_str() ); 20 | 21 | pFunction = scriptModule.GetFunctionByDecl( szName.c_str() ); 22 | 23 | scriptModule.SetDefaultNamespace( szOldNS.c_str() ); 24 | 25 | pFunction = scriptModule.GetFunctionByDecl( szName.c_str() ); 26 | } 27 | else 28 | { 29 | pFunction = scriptModule.GetFunctionByName( szName.c_str() ); 30 | 31 | const std::string szNS = as::ExtractNamespaceFromName( szName ); 32 | const std::string szActualName = as::ExtractNameFromName( szName ); 33 | 34 | const asUINT uiCount = scriptModule.GetFunctionCount(); 35 | 36 | for( asUINT uiIndex = 0; uiIndex < uiCount; ++uiIndex ) 37 | { 38 | auto pFunc = scriptModule.GetFunctionByIndex( uiIndex ); 39 | 40 | if( szActualName == pFunc->GetName() && szNS == pFunc->GetNamespace() ) 41 | { 42 | pFunction = pFunc; 43 | break; 44 | } 45 | } 46 | } 47 | 48 | if( pFunction ) 49 | pFunction->AddRef(); 50 | 51 | return pFunction; 52 | } 53 | 54 | asUINT CASModuleReflectionGroup::GetGlobalFunctionCount() const 55 | { 56 | auto& scriptModule = *GetScriptModuleFromScriptContext( asGetActiveContext() ); 57 | 58 | return scriptModule.GetFunctionCount(); 59 | } 60 | 61 | asIScriptFunction* CASModuleReflectionGroup::GetGlobalFunctionByIndex( asUINT uiIndex ) 62 | { 63 | auto& scriptModule = *GetScriptModuleFromScriptContext( asGetActiveContext() ); 64 | 65 | if( auto pFunction = scriptModule.GetFunctionByIndex( uiIndex ) ) 66 | { 67 | pFunction->AddRef(); 68 | return pFunction; 69 | } 70 | 71 | return nullptr; 72 | } 73 | 74 | asITypeInfo* CASModuleReflectionGroup::FindTypeInfo( const std::string& szName, bool bSearchByDecl ) 75 | { 76 | auto& scriptModule = *GetScriptModuleFromScriptContext( asGetActiveContext() ); 77 | 78 | const std::string szOldNS = scriptModule.GetDefaultNamespace(); 79 | 80 | asITypeInfo* pType; 81 | 82 | if( bSearchByDecl ) 83 | { 84 | const std::string szNS = as::ExtractNamespaceFromDecl( szName, false ); 85 | 86 | scriptModule.SetDefaultNamespace( szNS.c_str() ); 87 | 88 | pType = scriptModule.GetTypeInfoByDecl( szName.c_str() ); 89 | } 90 | else 91 | { 92 | const std::string szNS = as::ExtractNamespaceFromName( szName ); 93 | const std::string szActualName = as::ExtractNameFromName( szName ); 94 | 95 | scriptModule.SetDefaultNamespace( szNS.c_str() ); 96 | 97 | pType = scriptModule.GetTypeInfoByName( szActualName.c_str() ); 98 | } 99 | 100 | scriptModule.SetDefaultNamespace( szOldNS.c_str() ); 101 | 102 | if( pType ) 103 | pType->AddRef(); 104 | 105 | return pType; 106 | } 107 | 108 | asUINT CASModuleReflectionGroup::GetObjectTypeCount() const 109 | { 110 | auto& scriptModule = *GetScriptModuleFromScriptContext( asGetActiveContext() ); 111 | 112 | return scriptModule.GetObjectTypeCount(); 113 | } 114 | 115 | asITypeInfo* CASModuleReflectionGroup::GetObjectTypeByIndex( asUINT uiIndex ) 116 | { 117 | auto& scriptModule = *GetScriptModuleFromScriptContext( asGetActiveContext() ); 118 | 119 | if( auto pType = scriptModule.GetObjectTypeByIndex( uiIndex ) ) 120 | { 121 | pType->AddRef(); 122 | return pType; 123 | } 124 | 125 | return nullptr; 126 | } -------------------------------------------------------------------------------- /src/AngelscriptUtils/ScriptAPI/Reflection/CASModuleReflectionGroup.h: -------------------------------------------------------------------------------- 1 | #ifndef ANGELSCRIPT_SCRIPTAPI_REFLECTION_CASMODULEREFLECTIONGROUP_H 2 | #define ANGELSCRIPT_SCRIPTAPI_REFLECTION_CASMODULEREFLECTIONGROUP_H 3 | 4 | #include "IASReflectionGroup.h" 5 | 6 | class CASModuleReflectionGroup : public IASReflectionGroup 7 | { 8 | public: 9 | CASModuleReflectionGroup( ) = default; 10 | ~CASModuleReflectionGroup() = default; 11 | 12 | asIScriptFunction* FindGlobalFunction( const std::string& szName, bool bSearchByDecl = false ) override; 13 | 14 | asUINT GetGlobalFunctionCount() const override; 15 | 16 | asIScriptFunction* GetGlobalFunctionByIndex( asUINT uiIndex ) override; 17 | 18 | asITypeInfo* FindTypeInfo( const std::string& szName, bool bSearchByDecl = false ) override; 19 | 20 | asUINT GetObjectTypeCount() const override; 21 | 22 | asITypeInfo* GetObjectTypeByIndex( asUINT uiIndex ) override; 23 | 24 | private: 25 | CASModuleReflectionGroup( const CASModuleReflectionGroup& ) = delete; 26 | CASModuleReflectionGroup& operator=( const CASModuleReflectionGroup& ) = delete; 27 | }; 28 | 29 | #endif //ANGELSCRIPT_SCRIPTAPI_REFLECTION_CASMODULEREFLECTIONGROUP_H -------------------------------------------------------------------------------- /src/AngelscriptUtils/ScriptAPI/Reflection/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_sources( 2 | IASReflectionGroup.h 3 | CASEngineReflectionGroup.h 4 | CASEngineReflectionGroup.cpp 5 | CASModuleReflectionGroup.h 6 | CASModuleReflectionGroup.cpp 7 | ASReflection.h 8 | ASReflection.cpp 9 | ) 10 | 11 | add_includes( 12 | IASReflectionGroup.h 13 | CASEngineReflectionGroup.h 14 | CASModuleReflectionGroup.h 15 | ASReflection.h 16 | ) -------------------------------------------------------------------------------- /src/AngelscriptUtils/ScriptAPI/Reflection/IASReflectionGroup.h: -------------------------------------------------------------------------------- 1 | #ifndef ANGELSCRIPT_SCRIPTAPI_REFLECTION_IASREFLECTIONGROUP_H 2 | #define ANGELSCRIPT_SCRIPTAPI_REFLECTION_IASREFLECTIONGROUP_H 3 | 4 | #include 5 | 6 | #include 7 | 8 | class IASReflectionGroup 9 | { 10 | public: 11 | virtual ~IASReflectionGroup() = 0; 12 | 13 | virtual asIScriptFunction* FindGlobalFunction( const std::string& szName, bool bSearchByDecl = false ) = 0; 14 | 15 | virtual asUINT GetGlobalFunctionCount() const = 0; 16 | 17 | virtual asIScriptFunction* GetGlobalFunctionByIndex( asUINT uiIndex ) = 0; 18 | 19 | virtual asITypeInfo* FindTypeInfo( const std::string& szName, bool bSearchByDecl = false ) = 0; 20 | 21 | virtual asUINT GetObjectTypeCount() const = 0; 22 | 23 | virtual asITypeInfo* GetObjectTypeByIndex( asUINT uiIndex ) = 0; 24 | }; 25 | 26 | inline IASReflectionGroup::~IASReflectionGroup() 27 | { 28 | } 29 | 30 | #endif //ANGELSCRIPT_SCRIPTAPI_REFLECTION_IASREFLECTIONGROUP_H -------------------------------------------------------------------------------- /src/AngelscriptUtils/add_on/scriptbuilder/scriptbuilder.h: -------------------------------------------------------------------------------- 1 | #ifndef SCRIPTBUILDER_H 2 | #define SCRIPTBUILDER_H 3 | 4 | //--------------------------- 5 | // Compilation settings 6 | // 7 | 8 | // Set this flag to turn on/off metadata processing 9 | // 0 = off 10 | // 1 = on 11 | #ifndef AS_PROCESS_METADATA 12 | #define AS_PROCESS_METADATA 1 13 | #endif 14 | 15 | // TODO: Implement flags for turning on/off include directives and conditional programming 16 | 17 | 18 | 19 | //--------------------------- 20 | // Declaration 21 | // 22 | 23 | #ifndef ANGELSCRIPT_H 24 | // Avoid having to inform include path if header is already include before 25 | #include 26 | #endif 27 | 28 | 29 | #if defined(_MSC_VER) && _MSC_VER <= 1200 30 | // disable the annoying warnings on MSVC 6 31 | #pragma warning (disable:4786) 32 | #endif 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include // _strcmpi 39 | 40 | BEGIN_AS_NAMESPACE 41 | 42 | class CScriptBuilder; 43 | 44 | // This callback will be called for each #include directive encountered by the 45 | // builder. The callback should call the AddSectionFromFile or AddSectionFromMemory 46 | // to add the included section to the script. If the include cannot be resolved 47 | // then the function should return a negative value to abort the compilation. 48 | typedef int (*INCLUDECALLBACK_t)(const char *include, const char *from, CScriptBuilder *builder, void *userParam); 49 | 50 | // Helper class for loading and pre-processing script files to 51 | // support include directives and metadata declarations 52 | class CScriptBuilder 53 | { 54 | public: 55 | CScriptBuilder(); 56 | 57 | // Start a new module 58 | int StartNewModule(asIScriptEngine *engine, const char *moduleName); 59 | 60 | // Load a script section from a file on disk 61 | // Returns 1 if the file was included 62 | // 0 if the file had already been included before 63 | // <0 on error 64 | int AddSectionFromFile(const char *filename); 65 | 66 | // Load a script section from memory 67 | // Returns 1 if the section was included 68 | // 0 if a section with the same name had already been included before 69 | // <0 on error 70 | int AddSectionFromMemory(const char *sectionName, 71 | const char *scriptCode, 72 | unsigned int scriptLength = 0, 73 | int lineOffset = 0); 74 | 75 | // Build the added script sections 76 | int BuildModule(); 77 | 78 | // Returns the current module 79 | asIScriptModule *GetModule(); 80 | 81 | // Register the callback for resolving include directive 82 | void SetIncludeCallback(INCLUDECALLBACK_t callback, void *userParam); 83 | 84 | // Add a pre-processor define for conditional compilation 85 | void DefineWord(const char *word); 86 | 87 | // Enumerate included script sections 88 | unsigned int GetSectionCount() const; 89 | std::string GetSectionName(unsigned int idx) const; 90 | 91 | #if AS_PROCESS_METADATA == 1 92 | // Get metadata declared for classes, interfaces, and enums 93 | const char *GetMetadataStringForType(int typeId); 94 | 95 | // Get metadata declared for functions 96 | const char *GetMetadataStringForFunc(asIScriptFunction *func); 97 | 98 | // Get metadata declared for global variables 99 | const char *GetMetadataStringForVar(int varIdx); 100 | 101 | // Get metadata declared for class variables 102 | const char *GetMetadataStringForTypeProperty(int typeId, int varIdx); 103 | 104 | // Get metadata declared for class methods 105 | const char *GetMetadataStringForTypeMethod(int typeId, asIScriptFunction *method); 106 | #endif 107 | 108 | protected: 109 | void ClearAll(); 110 | int Build(); 111 | int ProcessScriptSection(const char *script, unsigned int length, const char *sectionname, int lineOffset); 112 | int LoadScriptSection(const char *filename); 113 | bool IncludeIfNotAlreadyIncluded(const char *filename); 114 | 115 | int SkipStatement(int pos); 116 | 117 | int ExcludeCode(int start); 118 | void OverwriteCode(int start, int len); 119 | 120 | asIScriptEngine *engine; 121 | asIScriptModule *module; 122 | std::string modifiedScript; 123 | 124 | INCLUDECALLBACK_t includeCallback; 125 | void *callbackParam; 126 | 127 | #if AS_PROCESS_METADATA == 1 128 | int ExtractMetadataString(int pos, std::string &outMetadata); 129 | int ExtractDeclaration(int pos, std::string &outName, std::string &outDeclaration, int &outType); 130 | 131 | enum METADATATYPE 132 | { 133 | MDT_TYPE = 1, 134 | MDT_FUNC = 2, 135 | MDT_VAR = 3, 136 | MDT_VIRTPROP = 4, 137 | MDT_FUNC_OR_VAR = 5 138 | }; 139 | 140 | // Temporary structure for storing metadata and declaration 141 | struct SMetadataDecl 142 | { 143 | SMetadataDecl(std::string m, std::string n, std::string d, int t, std::string c, std::string ns) : metadata(m), name(n), declaration(d), type(t), parentClass(c), nameSpace(ns) {} 144 | std::string metadata; 145 | std::string name; 146 | std::string declaration; 147 | int type; 148 | std::string parentClass; 149 | std::string nameSpace; 150 | }; 151 | std::vector foundDeclarations; 152 | std::string currentClass; 153 | std::string currentNamespace; 154 | 155 | // Storage of metadata for global declarations 156 | std::map typeMetadataMap; 157 | std::map funcMetadataMap; 158 | std::map varMetadataMap; 159 | 160 | // Storage of metadata for class member declarations 161 | struct SClassMetadata 162 | { 163 | SClassMetadata(const std::string& aName) : className(aName) {} 164 | std::string className; 165 | std::map funcMetadataMap; 166 | std::map varMetadataMap; 167 | }; 168 | std::map classMetadataMap; 169 | 170 | #endif 171 | 172 | #ifdef _WIN32 173 | // On Windows the filenames are case insensitive so the comparisons to 174 | // avoid duplicate includes must also be case insensitive. True case insensitive 175 | // is not easy as it must be language aware, but a simple implementation such 176 | // as strcmpi should suffice in almost all cases. 177 | // 178 | // ref: http://www.gotw.ca/gotw/029.htm 179 | // ref: https://msdn.microsoft.com/en-us/library/windows/desktop/dd317761(v=vs.85).aspx 180 | // ref: http://site.icu-project.org/ 181 | 182 | // TODO: Strings by default are treated as UTF8 encoded. If the application choses to 183 | // use a different encoding, the comparison algorithm should be adjusted as well 184 | 185 | struct ci_less 186 | { 187 | bool operator()(const std::string &a, const std::string &b) const 188 | { 189 | return _strcmpi(a.c_str(), b.c_str()) < 0; 190 | } 191 | }; 192 | std::set includedScripts; 193 | #else 194 | std::set includedScripts; 195 | #endif 196 | 197 | std::set definedWords; 198 | }; 199 | 200 | END_AS_NAMESPACE 201 | 202 | #endif 203 | -------------------------------------------------------------------------------- /src/AngelscriptUtils/cmake/AngelscriptUtilsConfig.cmake: -------------------------------------------------------------------------------- 1 | include("${CMAKE_CURRENT_LIST_DIR}/AngelscriptUtilsTargets.cmake") 2 | -------------------------------------------------------------------------------- /src/AngelscriptUtils/event/CASBaseEvent.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "AngelscriptUtils/util/ASLogging.h" 5 | #include "AngelscriptUtils/util/ASUtil.h" 6 | 7 | #include "AngelscriptUtils/CASModule.h" 8 | 9 | #include "CASBaseEvent.h" 10 | 11 | CASBaseEvent::CASBaseEvent( const asDWORD accessMask ) 12 | : m_AccessMask( accessMask ) 13 | { 14 | assert( accessMask != 0 ); 15 | } 16 | 17 | CASBaseEvent::~CASBaseEvent() 18 | { 19 | RemoveAllFunctions(); 20 | } 21 | 22 | size_t CASBaseEvent::GetFunctionCount() const 23 | { 24 | return m_Functions.size(); 25 | } 26 | 27 | asIScriptFunction* CASBaseEvent::GetFunctionByIndex( const size_t uiIndex ) const 28 | { 29 | assert( uiIndex < m_Functions.size() ); 30 | 31 | return m_Functions[ uiIndex ]; 32 | } 33 | 34 | bool CASBaseEvent::AddFunction( asIScriptFunction* pFunction ) 35 | { 36 | assert( pFunction ); 37 | 38 | //Don't add functions while this event is being invoked. 39 | if( IsTriggering() ) 40 | { 41 | as::CASCallerInfo info; 42 | 43 | as::GetCallerInfo( info ); 44 | 45 | as::log->critical( "CBaseEvent::AddFunction: {}({}, {}): Cannot add function while invoking event!", info.pszSection, info.iLine, info.iColumn ); 46 | return false; 47 | } 48 | 49 | if( !pFunction ) 50 | return false; 51 | 52 | if( std::find( m_Functions.begin(), m_Functions.end(), pFunction ) != m_Functions.end() ) 53 | return true; 54 | 55 | m_Functions.push_back( pFunction ); 56 | 57 | pFunction->AddRef(); 58 | 59 | std::stable_sort( m_Functions.begin(), m_Functions.end(), []( const asIScriptFunction* pLHS, const asIScriptFunction* pRHS ) 60 | { 61 | auto pLHSModule = GetModuleFromScriptFunction( pLHS ); 62 | auto pRHSModule = GetModuleFromScriptFunction( pRHS ); 63 | 64 | return ModuleLess( pLHSModule, pRHSModule ); 65 | } ); 66 | 67 | return true; 68 | } 69 | 70 | bool CASBaseEvent::Hook( void* pValue, const int iTypeId ) 71 | { 72 | assert( pValue ); 73 | 74 | if( !pValue ) 75 | return false; 76 | 77 | asIScriptFunction* pFunction = nullptr; 78 | 79 | if( !ValidateHookFunction( iTypeId, pValue, "HookFunction", pFunction ) ) 80 | { 81 | return false; 82 | } 83 | 84 | return AddFunction( pFunction ); 85 | } 86 | 87 | void CASBaseEvent::RemoveFunction( asIScriptFunction* pFunction ) 88 | { 89 | if( !pFunction ) 90 | return; 91 | 92 | auto it = std::find( m_Functions.begin(), m_Functions.end(), pFunction ); 93 | 94 | if( it == m_Functions.end() ) 95 | return; 96 | 97 | ( *it )->Release(); 98 | 99 | if( IsTriggering() ) 100 | { 101 | //Currently triggering, mark as removed. 102 | *it = nullptr; 103 | } 104 | else 105 | { 106 | //Remove now. 107 | m_Functions.erase( it ); 108 | } 109 | } 110 | 111 | void CASBaseEvent::Unhook( void* pValue, const int iTypeId ) 112 | { 113 | assert( pValue ); 114 | 115 | if( !pValue ) 116 | return; 117 | 118 | asIScriptFunction* pFunction = nullptr; 119 | 120 | if( !ValidateHookFunction( iTypeId, pValue, "UnhookFunction", pFunction ) ) 121 | { 122 | return; 123 | } 124 | 125 | RemoveFunction( pFunction ); 126 | } 127 | 128 | void CASBaseEvent::RemoveFunctionsOfModule( CASModule* pModule ) 129 | { 130 | assert( pModule ); 131 | 132 | //This method should never be called while in an event invocation. 133 | if( IsTriggering() ) 134 | { 135 | assert( !"CBaseEvent::RemoveFunctionsOfModule: Module hooks should not be removed while invoking events!" ); 136 | 137 | as::CASCallerInfo info; 138 | 139 | as::GetCallerInfo( info ); 140 | 141 | as::log->critical( "CBaseEvent::RemoveFunctionsOfModule: {}({}, {}): Module hooks should not be removed while invoking events!", info.pszSection, info.iLine, info.iColumn ); 142 | return; 143 | } 144 | 145 | if( !pModule ) 146 | return; 147 | 148 | //These functions might be null in some edge cases due to hooks being removed in event calls. 149 | //Fixed version provided by HoraceWeebler - Solokiller 150 | m_Functions.erase( 151 | std::remove_if( 152 | m_Functions.begin(), 153 | m_Functions.end(), 154 | [ &pModule ]( const asIScriptFunction* pFunction ) -> bool 155 | { 156 | if( !pFunction ) 157 | return true; 158 | else if( pModule == GetModuleFromScriptFunction( pFunction ) ) 159 | { 160 | pFunction->Release(); 161 | return true; 162 | } 163 | else 164 | return false; 165 | } 166 | ), 167 | m_Functions.end() 168 | ); 169 | } 170 | 171 | void CASBaseEvent::RemoveAllFunctions() 172 | { 173 | //This method should never be called while in an event invocation. 174 | if( m_iInCallCount != 0 ) 175 | { 176 | assert( !"CASEvent::RemoveAllFunctions: Hooks should not be removed while invoking events!" ); 177 | as::log->critical( "CASEvent::RemoveAllFunctions: Hooks should not be removed while invoking events!" ); 178 | 179 | if( auto pContext = asGetActiveContext() ) 180 | { 181 | pContext->SetException( "Cannot remove event hooks during the event's invocation" ); 182 | } 183 | 184 | return; 185 | } 186 | 187 | for( auto pFunc : m_Functions ) 188 | { 189 | if( pFunc->GetDelegateFunction() ) 190 | pFunc->Release(); 191 | 192 | pFunc->Release(); 193 | } 194 | 195 | m_Functions.clear(); 196 | } 197 | 198 | bool CASBaseEvent::ValidateHookFunction( const int iTypeId, void* pObject, const char* const pszScope, asIScriptFunction*& pOutFunction ) const 199 | { 200 | auto pEngine = asGetActiveContext()->GetEngine(); 201 | 202 | pOutFunction = nullptr; 203 | 204 | asITypeInfo* pObjectType = pEngine->GetTypeInfoById( iTypeId ); 205 | 206 | if( !pObjectType ) 207 | { 208 | as::log->critical( "CBaseEvent::{}: unknown type!", pszScope ); 209 | return false; 210 | } 211 | 212 | if( !( pObjectType->GetFlags() & asOBJ_FUNCDEF ) ) 213 | { 214 | as::log->critical( "CBaseEvent::{}: Object is not a function or delegate!", pszScope ); 215 | return false; 216 | } 217 | 218 | if( !pObject ) 219 | { 220 | as::log->critical( "CBaseEvent::{}: Object is null!", pszScope ); 221 | return false; 222 | } 223 | 224 | //pObjectType->GetTypeId() is -1 for some reason 225 | if( iTypeId & asTYPEID_OBJHANDLE ) 226 | { 227 | pObject = *reinterpret_cast( pObject ); 228 | } 229 | 230 | if( !pObject ) 231 | { 232 | as::log->critical( "CBaseEvent::{}: Object is null!", pszScope ); 233 | return false; 234 | } 235 | 236 | asIScriptFunction* pFunction = reinterpret_cast( pObject ); 237 | 238 | if( !pFunction ) 239 | { 240 | as::log->critical( "CBaseEvent::{}: Null function passed!", pszScope ); 241 | return false; 242 | } 243 | 244 | asIScriptFunction* const pFuncDef = GetFuncDef(); 245 | 246 | assert( pFuncDef ); 247 | 248 | if( !pFuncDef ) 249 | { 250 | as::log->critical( "CBaseEvent::{}: No funcdef for event!", pszScope ); 251 | return false; 252 | } 253 | 254 | //Verify the function format 255 | if( !pFuncDef->IsCompatibleWithTypeId( pFunction->GetTypeId() ) ) 256 | { 257 | const auto szFunctionName = as::FormatFunctionName( *pFunction ); 258 | 259 | as::log->critical( "CBaseEvent::{}: Function '{}' is incompatible with event '{}'!", 260 | pszScope, szFunctionName, pFuncDef->GetName() ); 261 | 262 | return false; 263 | } 264 | 265 | pOutFunction = pFunction; 266 | 267 | return true; 268 | } 269 | 270 | void CASBaseEvent::DumpHookedFunctions( const char* const pszName ) const 271 | { 272 | if( pszName ) 273 | as::log->info( "{}", pszName ); 274 | 275 | for( size_t uiIndex = 0; uiIndex < GetFunctionCount(); ++uiIndex ) 276 | { 277 | auto pFunc = GetFunctionByIndex( uiIndex ); 278 | 279 | auto pModule = pFunc->GetModule(); 280 | 281 | if( !pModule ) 282 | { 283 | auto pDelegate = pFunc->GetDelegateFunction(); 284 | 285 | if( pDelegate ) 286 | { 287 | pModule = pDelegate->GetModule(); 288 | } 289 | } 290 | 291 | if( !pModule ) 292 | { 293 | as::log->info( "Null module!" ); 294 | continue; 295 | } 296 | 297 | const auto szFunctionName = as::FormatFunctionName( *pFunc ); 298 | as::log->info( "Module \"{}\", \"{}\"", pModule->GetName(), szFunctionName ); 299 | } 300 | 301 | as::log->info( "End functions" ); 302 | } 303 | 304 | void CASBaseEvent::ClearRemovedHooks() 305 | { 306 | //Can happen when recursively triggering events. 307 | if( IsTriggering() ) 308 | return; 309 | 310 | for( auto it = m_Functions.begin(); it != m_Functions.end(); ) 311 | { 312 | if( !( *it ) ) 313 | { 314 | it = m_Functions.erase( it ); 315 | } 316 | else 317 | { 318 | ++it; 319 | } 320 | } 321 | } 322 | 323 | void RegisterScriptCBaseEvent( asIScriptEngine& engine ) 324 | { 325 | const char* const pszObjectName = "CBaseEvent"; 326 | 327 | engine.RegisterObjectType( 328 | pszObjectName, 0, asOBJ_REF | asOBJ_NOCOUNT ); 329 | 330 | RegisterScriptCBaseEvent( engine, pszObjectName ); 331 | } 332 | -------------------------------------------------------------------------------- /src/AngelscriptUtils/event/CASBaseEvent.h: -------------------------------------------------------------------------------- 1 | #ifndef ANGELSCRIPT_CASBASEEVENT_H 2 | #define ANGELSCRIPT_CASBASEEVENT_H 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include "AngelscriptUtils/util/ASUtil.h" 9 | 10 | #include "AngelscriptUtils/wrapper/ASCallableConst.h" 11 | 12 | class CASModule; 13 | 14 | /** 15 | * @defgroup ASEvents Angelscript Events 16 | * 17 | * @{ 18 | */ 19 | 20 | /** 21 | * Represents an event that can be triggered, and that scripts can hook into to be notified when it is triggered. 22 | */ 23 | class CASBaseEvent 24 | { 25 | protected: 26 | template 27 | friend class CASBaseEventCaller; 28 | 29 | private: 30 | typedef std::vector Functions_t; 31 | 32 | public: 33 | /** 34 | * Constructor. 35 | * @param accessMask Access mask. Which module types this hook is available to. 36 | * @param stopMode Stop mode. 37 | * @see EventStopMode 38 | */ 39 | CASBaseEvent( const asDWORD accessMask ); 40 | ~CASBaseEvent(); 41 | 42 | /** 43 | * @return Access mask. 44 | */ 45 | asDWORD GetAccessMask() const { return m_AccessMask; } 46 | 47 | /** 48 | * @return The funcdef that represents this event. 49 | */ 50 | asIScriptFunction* GetFuncDef() const { return m_pFuncDef; } 51 | 52 | /** 53 | * Sets the funcdef that represents this event. 54 | * @param pFuncDef Funcdef. 55 | */ 56 | void SetFuncDef( asIScriptFunction* pFuncDef ) 57 | { 58 | m_pFuncDef = pFuncDef; 59 | } 60 | 61 | /** 62 | * @return Number of hooked functions. 63 | */ 64 | size_t GetFunctionCount() const; 65 | 66 | /** 67 | * Gets a hooked function by index. 68 | * @param uiIndex Index. 69 | * @return Function. 70 | */ 71 | asIScriptFunction* GetFunctionByIndex( const size_t uiIndex ) const; 72 | 73 | /** 74 | * Adds a new function. Cannot be called while this event is being called. 75 | * Warning: if the function does not match the event parameters and return type, this will cause problems. 76 | * @param pFunction Function to add. 77 | * @return true if the function was either added or already added before, false otherwise. 78 | */ 79 | bool AddFunction( asIScriptFunction* pFunction ); 80 | 81 | /** 82 | * Hooks a function to an event. 83 | * Used by scripts only. 84 | * @param pValue Function pointer. 85 | * @param iTypeId Function pointer type id. 86 | * @return true on success, false otherwise. 87 | */ 88 | bool Hook( void* pValue, const int iTypeId ); 89 | 90 | /** 91 | * Removes a function. Cannot be called while this event is being called. 92 | * @param pFunction Function to remove. 93 | */ 94 | void RemoveFunction( asIScriptFunction* pFunction ); 95 | 96 | /** 97 | * Unhooks a function from an event. 98 | * Used by scripts only. 99 | * @param pValue Function pointer. 100 | * @param iTypeId Function pointer type id. 101 | */ 102 | void Unhook( void* pValue, const int iTypeId ); 103 | 104 | /** 105 | * Removes all of the functions that belong to the given module. 106 | */ 107 | void RemoveFunctionsOfModule( CASModule* pModule ); 108 | 109 | /** 110 | * Removes all functions. 111 | */ 112 | void RemoveAllFunctions(); 113 | 114 | private: 115 | /** 116 | * Validates the given hook function. 117 | */ 118 | bool ValidateHookFunction( const int iTypeId, void* pObject, const char* const pszScope, asIScriptFunction*& pOutFunction ) const; 119 | 120 | public: 121 | 122 | /** 123 | * Dumps all hooked functions to stdout. 124 | * @param pszName Optional. Name to print. 125 | */ 126 | void DumpHookedFunctions( const char* const pszName ) const; 127 | 128 | /** 129 | * @return Whether this event is currently being triggered. 130 | */ 131 | bool IsTriggering() const { return m_iInCallCount != 0; } 132 | 133 | protected: 134 | /** 135 | * @return The call count. 136 | */ 137 | int GetCallCount() const 138 | { 139 | return m_iInCallCount; 140 | } 141 | 142 | /** 143 | * Increments the call count. 144 | */ 145 | void IncrementCallCount() 146 | { 147 | ++m_iInCallCount; 148 | } 149 | 150 | /** 151 | * Decrements the call count. 152 | */ 153 | void DecrementCallCount() 154 | { 155 | --m_iInCallCount; 156 | } 157 | 158 | /** 159 | * If a script called Unhook while in this event's hook invocation it'll leave behind a null pointer. 160 | * This cleans up those hooks. 161 | */ 162 | void ClearRemovedHooks(); 163 | 164 | private: 165 | const asDWORD m_AccessMask; 166 | 167 | asIScriptFunction* m_pFuncDef = nullptr; 168 | 169 | Functions_t m_Functions; 170 | 171 | //Used to prevent adding/removing hooks while invoking the hook in question. 172 | int m_iInCallCount = 0; 173 | 174 | private: 175 | CASBaseEvent( const CASBaseEvent& ) = delete; 176 | CASBaseEvent& operator=( const CASBaseEvent& ) = delete; 177 | }; 178 | 179 | /** 180 | * Registers CBaseEvent class members for pszObjectName. Also registers casts to and from pszObjectName if it differs from CBaseEvent. 181 | * @param engine Script engine. 182 | * @param pszObjectName Name of the class that is being registered. 183 | */ 184 | template 185 | void RegisterScriptCBaseEvent( asIScriptEngine& engine, const char* const pszObjectName ) 186 | { 187 | as::RegisterCasts( engine, "CBaseEvent", pszObjectName, &as::Cast_UpCast, &as::Cast_DownCast ); 188 | 189 | engine.RegisterObjectMethod( 190 | pszObjectName, "bool Hook(?& in pFunction)", 191 | asMETHOD( CLASS, Hook ), asCALL_THISCALL ); 192 | 193 | engine.RegisterObjectMethod( 194 | pszObjectName, "void Unhook(?& in pFunction)", 195 | asMETHOD( CLASS, Unhook ), asCALL_THISCALL ); 196 | } 197 | 198 | /** 199 | * Registers the CBaseEvent class. 200 | * @param engine Script engine. 201 | */ 202 | void RegisterScriptCBaseEvent( asIScriptEngine& engine ); 203 | 204 | /** @} */ 205 | 206 | #endif //ANGELSCRIPT_CASBASEEVENT_H 207 | -------------------------------------------------------------------------------- /src/AngelscriptUtils/event/CASBaseEventCaller.h: -------------------------------------------------------------------------------- 1 | #ifndef ANGELSCRIPT_CASBASEEVENTCALLER_H 2 | #define ANGELSCRIPT_CASBASEEVENTCALLER_H 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | #include "AngelscriptUtils/wrapper/ASCallable.h" 9 | 10 | /** 11 | * Base class for classes that can call events. 12 | * Uses the curiously recurring template pattern. 13 | * 14 | * The subclass is required to provide a few things: 15 | * A method with this format: 16 | * ReturnType_t CallEvent( EventType_t& event, asIScriptContext* pContext, CallFlags_t flags, va_list list ) 17 | * This method will perform the actual call to the hook. 18 | * 19 | * @tparam SUBCLASS Class that inherits from this class. 20 | * @tparam EVENTTYPE Represents the type of the event being called. 21 | * @tparam RETURNTYPE Type that will be returned by call methods. 22 | * @tparam FAILEDRETURNVAL Value to return when a call fails. 23 | */ 24 | template 25 | class CASBaseEventCaller 26 | { 27 | public: 28 | /** 29 | * Type of the subclass. 30 | */ 31 | typedef SUBCLASS SubClass_t; 32 | 33 | /** 34 | * Type of the event being called. 35 | */ 36 | typedef EVENTTYPE EventType_t; 37 | 38 | /** 39 | * Type of the return value. 40 | */ 41 | typedef RETURNTYPE ReturnType_t; 42 | 43 | /** 44 | * Return value when the call fails. 45 | */ 46 | static const RETURNTYPE FAILED_RETURN_VALUE = FAILEDRETURNVAL; 47 | 48 | public: 49 | //Can be instanced and have member vars for call specific state. 50 | CASBaseEventCaller() = default; 51 | ~CASBaseEventCaller() = default; 52 | 53 | //Copyable 54 | CASBaseEventCaller( const CASBaseEventCaller& other ) = default; 55 | CASBaseEventCaller& operator=( const CASBaseEventCaller& ) = default; 56 | 57 | //Movable 58 | CASBaseEventCaller( CASBaseEventCaller&& other ) {} 59 | CASBaseEventCaller& operator=( CASBaseEventCaller&& ) {} 60 | 61 | /** 62 | * Forwards the call to the subclass. 63 | */ 64 | inline ReturnType_t VCall( EventType_t& event, asIScriptContext* pContext, CallFlags_t flags, va_list list ) 65 | { 66 | //Take care of some common bookkeeping here. 67 | assert( pContext ); 68 | 69 | if( !pContext ) 70 | return FAILED_RETURN_VALUE; 71 | 72 | IncrementCallCount( event ); 73 | 74 | auto result = static_cast( this )->CallEvent( event, pContext, flags, list ); 75 | 76 | DecrementCallCount( event ); 77 | 78 | assert( GetCallCount( event ) >= 0 ); 79 | 80 | //Clear any removed hooks. 81 | event.ClearRemovedHooks(); 82 | 83 | return result; 84 | } 85 | 86 | /** 87 | * Calls the given event using the given context. 88 | * @param event Event to call. 89 | * @param pContext Context to use. 90 | * @param list Arguments. 91 | */ 92 | inline ReturnType_t VCall( EventType_t& event, asIScriptContext* pContext, va_list list ) 93 | { 94 | return VCall( event, pContext, CallFlag::NONE, list ); 95 | } 96 | 97 | /** 98 | * Calls the given event using a context acquired from the given engine. 99 | * @param event Event to call. 100 | * @param pScriptEngine Script engine to use. 101 | * @param flags Call flags. 102 | * @param list Arguments. 103 | */ 104 | inline ReturnType_t VCall( EventType_t& event, asIScriptEngine* pScriptEngine, CallFlags_t flags, va_list list ) 105 | { 106 | auto pContext = pScriptEngine->RequestContext(); 107 | 108 | auto result = VCall( event, pContext, flags, list ); 109 | 110 | pScriptEngine->ReturnContext( pContext ); 111 | 112 | return result; 113 | } 114 | 115 | /** 116 | * Calls the given event using a context acquired from the given engine. 117 | * @param event Event to call. 118 | * @param pScriptEngine Script engine to use. 119 | * @param list Arguments. 120 | */ 121 | inline ReturnType_t VCall( EventType_t& event, asIScriptEngine* pScriptEngine, va_list list ) 122 | { 123 | auto pContext = pScriptEngine->RequestContext(); 124 | 125 | auto result = VCall( event, pContext, CallFlag::NONE, list ); 126 | 127 | pScriptEngine->ReturnContext( pContext ); 128 | 129 | return result; 130 | } 131 | 132 | /** 133 | * Calls the given event using the given context. 134 | * @param event Event to call. 135 | * @param pContext Context to use. 136 | * @param flags Flags. 137 | * @param ... Arguments. 138 | */ 139 | inline ReturnType_t Call( EventType_t& event, asIScriptContext* pContext, CallFlags_t flags, ... ) 140 | { 141 | va_list list; 142 | 143 | va_start( list, flags ); 144 | 145 | auto result = VCall( event, pContext, flags, list ); 146 | 147 | va_end( list ); 148 | 149 | return result; 150 | } 151 | 152 | /** 153 | * @see Call( EventType_t& event, asIScriptContext* pContext, CallFlags_t flags, ... ) 154 | */ 155 | inline ReturnType_t Call( EventType_t& event, asIScriptContext* pContext, ... ) 156 | { 157 | va_list list; 158 | 159 | va_start( list, pContext ); 160 | 161 | auto result = VCall( event, pContext, list ); 162 | 163 | va_end( list ); 164 | 165 | return result; 166 | } 167 | 168 | /** 169 | * Calls the given event using a context acquired from the given engine. 170 | * @param event Event to call. 171 | * @param pScriptEngine Script engine to use. 172 | * @param flags Call flags. 173 | * @param ... Arguments. 174 | */ 175 | inline ReturnType_t Call( EventType_t& event, asIScriptEngine* pScriptEngine, CallFlags_t flags, ... ) 176 | { 177 | va_list list; 178 | 179 | va_start( list, flags ); 180 | 181 | auto result = VCall( event, pScriptEngine, flags, list ); 182 | 183 | va_end( list ); 184 | 185 | return result; 186 | } 187 | 188 | /** 189 | * Calls the given event using a context acquired from the given engine. 190 | * @param event Event to call. 191 | * @param pScriptEngine Script engine to use. 192 | * @param ... Arguments. 193 | */ 194 | inline ReturnType_t Call( EventType_t& event, asIScriptEngine* pScriptEngine, ... ) 195 | { 196 | va_list list; 197 | 198 | va_start( list, pScriptEngine ); 199 | 200 | auto result = VCall( event, pScriptEngine, list ); 201 | 202 | va_end( list ); 203 | 204 | return result; 205 | } 206 | 207 | protected: 208 | //These provide access to the event's call counter 209 | int GetCallCount( EventType_t& event ) 210 | { 211 | return event.GetCallCount(); 212 | } 213 | 214 | void IncrementCallCount( EventType_t& event ) 215 | { 216 | event.IncrementCallCount(); 217 | } 218 | 219 | void DecrementCallCount( EventType_t& event ) 220 | { 221 | event.DecrementCallCount(); 222 | } 223 | }; 224 | 225 | #endif //ANGELSCRIPT_CASBASEEVENTCALLER_H 226 | -------------------------------------------------------------------------------- /src/AngelscriptUtils/event/CASEvent.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "CASEvent.h" 4 | 5 | CASEvent::CASEvent( const char* const pszName, const char* pszArguments, const char* const pszCategory, const asDWORD accessMask, const EventStopMode stopMode ) 6 | : CASBaseEvent( accessMask ) 7 | , m_pszName( pszName ) 8 | , m_pszArguments( pszArguments ) 9 | , m_pszCategory( pszCategory ) 10 | , m_StopMode( stopMode ) 11 | { 12 | assert( pszName ); 13 | assert( pszArguments ); 14 | assert( pszCategory ); 15 | } 16 | 17 | void CASEvent::DumpHookedFunctions() const 18 | { 19 | CASBaseEvent::DumpHookedFunctions( ( std::string( "Event \"" ) + GetCategory() + "::" + GetName() + '(' + GetArguments() + ")\"" ).c_str() ); 20 | } 21 | 22 | void RegisterScriptCEvent( asIScriptEngine& engine ) 23 | { 24 | const char* const pszObjectName = "CEvent"; 25 | 26 | engine.RegisterObjectType( 27 | pszObjectName, 0, asOBJ_REF | asOBJ_NOCOUNT ); 28 | 29 | RegisterScriptCBaseEvent( engine, pszObjectName ); 30 | } 31 | -------------------------------------------------------------------------------- /src/AngelscriptUtils/event/CASEvent.h: -------------------------------------------------------------------------------- 1 | #ifndef ANGELSCRIPT_CASEVENT_H 2 | #define ANGELSCRIPT_CASEVENT_H 3 | 4 | #include 5 | 6 | #include "CASBaseEvent.h" 7 | 8 | /** 9 | * @addtogroup ASEvents 10 | * 11 | * @{ 12 | */ 13 | 14 | /** 15 | * Stop modes for events. Allows you to specify whether events should continue executing after a function has handled it. 16 | */ 17 | enum class EventStopMode 18 | { 19 | /** 20 | * Call all functions no matter what. 21 | */ 22 | CALL_ALL, 23 | 24 | /** 25 | * If any function in a module has handled the event, stop after executing the last function in that module. 26 | */ 27 | MODULE_HANDLED, 28 | 29 | /** 30 | * Stop as soon as a function has handled it. 31 | */ 32 | ON_HANDLED 33 | }; 34 | 35 | /** 36 | * Represents an event that script functions can hook into. 37 | */ 38 | class CASEvent final : public CASBaseEvent 39 | { 40 | public: 41 | /** 42 | * Constructor. 43 | * @param pszName Name of this event. 44 | * @param pszArguments The arguments passed to hooked functions. This is a comma delimited list of argument types, e.g. "const string& in, bool& out". 45 | * @param pszCategory Which category this hook is in. This is a double colon delimited list, e.g. "Game::Player". 46 | * @param accessMask Access mask. Which module types this hook is available to. 47 | * @param stopMode Stop mode. 48 | * @see EventStopMode 49 | */ 50 | CASEvent( const char* const pszName, const char* pszArguments, const char* const pszCategory, const asDWORD accessMask, const EventStopMode stopMode ); 51 | 52 | /** 53 | * @return Hook name. 54 | */ 55 | const char* GetName() const { return m_pszName; } 56 | 57 | /** 58 | * @return Hook arguments. 59 | */ 60 | const char* GetArguments() const { return m_pszArguments; } 61 | 62 | /** 63 | * @return Hook category. 64 | */ 65 | const char* GetCategory() const { return m_pszCategory; } 66 | 67 | /** 68 | * @return Stop mode. 69 | */ 70 | EventStopMode GetStopMode() const { return m_StopMode; } 71 | 72 | /** 73 | * Dumps all hooked functions to stdout. 74 | */ 75 | void DumpHookedFunctions() const; 76 | 77 | private: 78 | const char* const m_pszName; 79 | const char* const m_pszArguments; 80 | const char* const m_pszCategory; 81 | 82 | const EventStopMode m_StopMode; 83 | 84 | private: 85 | CASEvent( const CASEvent& ) = delete; 86 | CASEvent& operator=( const CASEvent& ) = delete; 87 | }; 88 | /** 89 | * Registers the CASEvent class. 90 | * @param engine Script engine. 91 | */ 92 | void RegisterScriptCEvent( asIScriptEngine& engine ); 93 | 94 | /** @} */ 95 | 96 | #endif //ANGELSCRIPT_CASEVENT_H 97 | -------------------------------------------------------------------------------- /src/AngelscriptUtils/event/CASEventCaller.cpp: -------------------------------------------------------------------------------- 1 | #include "CASEventCaller.h" 2 | 3 | CASEventCaller::ReturnType_t CASEventCaller::CallEvent( EventType_t& event, asIScriptContext* pContext, CallFlags_t flags, va_list list ) 4 | { 5 | CASContext ctx( *pContext ); 6 | 7 | bool bSuccess = true; 8 | 9 | HookReturnCode returnCode = HookReturnCode::CONTINUE; 10 | 11 | asIScriptModule* pLastModule = nullptr; 12 | 13 | decltype( event.GetFunctionByIndex( 0 ) ) pFunc; 14 | 15 | for( decltype( event.GetFunctionCount() ) index = 0; index < event.GetFunctionCount(); ++index ) 16 | { 17 | pFunc = event.GetFunctionByIndex( index ); 18 | 19 | if( !pFunc ) 20 | { 21 | //Function was removed in a hook call, skip. 22 | continue; 23 | } 24 | 25 | if( event.GetStopMode() == EventStopMode::MODULE_HANDLED && returnCode == HookReturnCode::HANDLED ) 26 | { 27 | //A hook in the last module handled it, so stop. 28 | if( pLastModule && pLastModule != pFunc->GetModule() ) 29 | break; 30 | } 31 | 32 | pLastModule = pFunc->GetModule(); 33 | 34 | CASFunction func( *pFunc, ctx ); 35 | 36 | //The hook might remove itself from the list, so make sure we still have a strong reference. 37 | pFunc->AddRef(); 38 | 39 | const auto successCall = func.VCall( flags, list ); 40 | 41 | pFunc->Release(); 42 | 43 | bSuccess = successCall && bSuccess; 44 | 45 | //Only check if a HANDLED value was returned if we're still continuing. 46 | if( successCall && returnCode == HookReturnCode::CONTINUE ) 47 | { 48 | bSuccess = func.GetReturnValue( &returnCode ) && bSuccess; 49 | } 50 | 51 | if( returnCode == HookReturnCode::HANDLED ) 52 | { 53 | if( event.GetStopMode() == EventStopMode::ON_HANDLED ) 54 | break; 55 | } 56 | } 57 | 58 | if( !bSuccess ) 59 | return HookCallResult::FAILED; 60 | 61 | return returnCode == HookReturnCode::HANDLED ? HookCallResult::HANDLED : HookCallResult::NONE_HANDLED; 62 | } 63 | 64 | void RegisterScriptHookReturnCode( asIScriptEngine& engine ) 65 | { 66 | const char* const pszObjectName = "HookReturnCode"; 67 | 68 | int result = engine.RegisterEnum( pszObjectName ); 69 | 70 | assert( result >= 0 ); 71 | 72 | result = engine.RegisterEnumValue( pszObjectName, "HOOK_CONTINUE", static_cast( HookReturnCode::CONTINUE ) ); 73 | assert( result >= 0 ); 74 | 75 | result = engine.RegisterEnumValue( pszObjectName, "HOOK_HANDLED", static_cast( HookReturnCode::HANDLED ) ); 76 | assert( result >= 0 ); 77 | } 78 | -------------------------------------------------------------------------------- /src/AngelscriptUtils/event/CASEventCaller.h: -------------------------------------------------------------------------------- 1 | #ifndef ANGELSCRIPT_CASEVENTCALLER_H 2 | #define ANGELSCRIPT_CASEVENTCALLER_H 3 | 4 | #include "CASBaseEventCaller.h" 5 | 6 | #include "CASEvent.h" 7 | 8 | /** 9 | * @addtogroup ASEvents 10 | * 11 | * @{ 12 | */ 13 | 14 | /** 15 | * Return codes for functions that hook into an event. 16 | */ 17 | enum class HookReturnCode 18 | { 19 | /** 20 | * Continue executing. 21 | */ 22 | CONTINUE, 23 | 24 | /** 25 | * The function handled the event, stop. 26 | */ 27 | HANDLED 28 | }; 29 | 30 | /** 31 | * Result codes for hook invocation. 32 | */ 33 | enum class HookCallResult 34 | { 35 | /** 36 | * An error occurred while executing the hook. 37 | */ 38 | FAILED, 39 | 40 | /** 41 | * No functions handled the hook. 42 | */ 43 | NONE_HANDLED, 44 | 45 | /** 46 | * One or more functions handled the hook. 47 | */ 48 | HANDLED 49 | }; 50 | 51 | /** 52 | * Class that can call CASEvent classes. 53 | */ 54 | class CASEventCaller : public CASBaseEventCaller 55 | { 56 | public: 57 | ReturnType_t CallEvent( EventType_t& event, asIScriptContext* pContext, CallFlags_t flags, va_list list ); 58 | }; 59 | 60 | /** 61 | * Registers the HookReturnCode enum. 62 | * @param engine Script engine. 63 | */ 64 | void RegisterScriptHookReturnCode( asIScriptEngine& engine ); 65 | 66 | /** @} */ 67 | 68 | #endif //ANGELSCRIPT_CASEVENTCALLER_H 69 | -------------------------------------------------------------------------------- /src/AngelscriptUtils/event/CASEventManager.h: -------------------------------------------------------------------------------- 1 | #ifndef ANGELSCRIPT_CASEVENTMANAGER_H 2 | #define ANGELSCRIPT_CASEVENTMANAGER_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | class asIScriptEngine; 11 | class CASModule; 12 | class CASEvent; 13 | 14 | /** 15 | * @addtogroup ASEvents 16 | * 17 | * @{ 18 | */ 19 | 20 | /** 21 | * Manages a list of global events. 22 | * Can store a maximum of UINT32_MAX events. 23 | */ 24 | class CASEventManager final 25 | { 26 | private: 27 | typedef std::vector Events_t; 28 | 29 | public: 30 | /** 31 | * Constructor. 32 | * @param engine Engine. 33 | * @param pszNamespace Namespace to register events in. Can be an empty string, in which case no namespace is used. 34 | */ 35 | CASEventManager( asIScriptEngine& engine, const char* const pszNamespace = "" ); 36 | 37 | /** 38 | * Destructor. 39 | */ 40 | ~CASEventManager(); 41 | 42 | /** 43 | * @return The script engine. 44 | */ 45 | asIScriptEngine& GetEngine() { return m_Engine; } 46 | 47 | /** 48 | * @return The number of events. 49 | */ 50 | uint32_t GetEventCount() const { return static_cast( m_Events.size() ); } 51 | 52 | /** 53 | * Gets an event by index. 54 | * @param uiIndex Event index. Must be smaller than GetEventCount(). 55 | * @return If the index is valid, the event. Otherwise, null. 56 | */ 57 | CASEvent* GetEventByIndex( const uint32_t uiIndex ); 58 | 59 | /** 60 | * Finds an event by its name. The given name must specify its category if it has one. 61 | * Format: \::\ 62 | * May optionally specify Events:: as the start of the category. 63 | * @return If found, the event. Otherwise, null. 64 | */ 65 | CASEvent* FindEventByName( const std::string& szName ); 66 | 67 | /** 68 | * Hooks a named event. The given name must specify its category if it has one. 69 | * Format: \::\ 70 | * May optionally specify Events:: as the start of the category. 71 | * @param szName Name of the event. 72 | * @param pValue Function pointer. 73 | * @param iTypeId Function pointer type id. 74 | * @return true on success, false otherwise. 75 | */ 76 | bool HookEvent( const std::string& szName, void* pValue, const int iTypeId ); 77 | 78 | /** 79 | * Unhooks a named event. The given name must specify its category if it has one. 80 | * Format: \::\ 81 | * May optionally specify Events:: as the start of the category. 82 | * @param szName Name of the event. 83 | * @param pValue Function pointer. 84 | * @param iTypeId Function pointer type id. 85 | */ 86 | void UnhookEvent( const std::string& szName, void* pValue, const int iTypeId ); 87 | 88 | /** 89 | * Adds an event. 90 | * @param pEvent Event to add. 91 | * @return true if the event was added, false otherwise. 92 | */ 93 | bool AddEvent( CASEvent* pEvent ); 94 | 95 | /** 96 | * Registers this class instance and all events. 97 | */ 98 | void RegisterEvents( asIScriptEngine& engine ); 99 | 100 | /** 101 | * Unhooks all functions that are part of the given module. 102 | * @param pModule Module. 103 | */ 104 | void UnhookModuleFunctions( CASModule* pModule ); 105 | 106 | /** 107 | * Unhooks all functions. 108 | */ 109 | void UnhookAllFunctions(); 110 | 111 | /** 112 | * Dumps all hooked functions to stdout. 113 | */ 114 | void DumpHookedFunctions() const; 115 | 116 | private: 117 | asIScriptEngine& m_Engine; 118 | 119 | std::string m_szNamespace; 120 | 121 | Events_t m_Events; 122 | 123 | private: 124 | CASEventManager( const CASEventManager& ) = delete; 125 | CASEventManager& operator=( const CASEventManager& ) = delete; 126 | }; 127 | 128 | /** 129 | * Registers the event API. 130 | * @param engine Script engine. 131 | */ 132 | void RegisterScriptEventAPI( asIScriptEngine& engine ); 133 | 134 | /** @} */ 135 | 136 | #endif //ANGELSCRIPT_CASEVENTMANAGER_H 137 | -------------------------------------------------------------------------------- /src/AngelscriptUtils/event/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_sources( 2 | CASBaseEvent.h 3 | CASBaseEvent.cpp 4 | CASBaseEventCaller.h 5 | CASEvent.h 6 | CASEvent.cpp 7 | CASEventCaller.h 8 | CASEventCaller.cpp 9 | CASEventManager.h 10 | CASEventManager.cpp 11 | ) 12 | 13 | add_includes( 14 | CASBaseEvent.h 15 | CASBaseEventCaller.h 16 | CASEvent.h 17 | CASEventCaller.h 18 | CASEventManager.h 19 | ) 20 | -------------------------------------------------------------------------------- /src/AngelscriptUtils/std_make_unique.h: -------------------------------------------------------------------------------- 1 | #ifndef STD_MAKE_UNIQUE_H 2 | #define STD_MAKE_UNIQUE_H 3 | 4 | // Shepard - This header file fixes missing "std::make_unique" for C++11 5 | // compilers, taken from this StackOverflow post: 6 | // https://stackoverflow.com/questions/17902405/how-to-implement-make-unique-function-in-c11 7 | 8 | #ifndef WIN32 9 | #if (__cplusplus >= 201103L && __cplusplus < 201402L) 10 | namespace std 11 | { 12 | template 13 | unique_ptr make_unique(Args&&... args) 14 | { 15 | return unique_ptr(new T(forward(args)...)); 16 | } 17 | } 18 | #endif // (__cplusplus >= 201103L && __cplusplus < 201402L) 19 | #endif // WIN32 20 | 21 | #endif // STD_MAKE_UNIQUE_H 22 | -------------------------------------------------------------------------------- /src/AngelscriptUtils/util/ASExtendAdapter.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "AngelscriptUtils/wrapper/ASCallable.h" 5 | 6 | #include "IASExtendAdapter.h" 7 | 8 | #include "ASExtendAdapter.h" 9 | 10 | namespace as 11 | { 12 | std::string CreateExtendBaseclassDeclaration( 13 | const char* const pszClassName, const char* const pszBaseClassName, 14 | const char* const pszCPPClassName, const char* const pszCPPBaseClassName, 15 | const char* const pszClassContents ) 16 | { 17 | assert( pszClassName ); 18 | assert( pszBaseClassName ); 19 | assert( pszCPPClassName ); 20 | 21 | std::stringstream stream; 22 | 23 | stream << "class " << pszClassName << " : " << pszBaseClassName << std::endl 24 | << '{' << std::endl; 25 | 26 | //Provide the self member. 27 | stream << "\tprivate " << pszCPPClassName << "@ m_pSelf;" << std::endl; 28 | 29 | stream << "\tprivate void SetSelf( " << pszCPPClassName << "@ self )" << std::endl 30 | << "\t{" << std::endl 31 | << "\t\t@this.m_pSelf = self;" << std::endl 32 | << "\t}" << std::endl 33 | << "\t" << pszCPPClassName << "@ get_self() const { return m_pSelf; }" << std::endl; 34 | 35 | //If the user has provided a baseclass type, provide the BaseClass member. 36 | if( pszCPPBaseClassName ) 37 | { 38 | stream << "\tprivate " << pszCPPBaseClassName << "@ m_pBaseClass;" << std::endl; 39 | 40 | stream << "\tprivate void SetBaseClass( " << pszCPPBaseClassName << "@ BaseClass )" << std::endl 41 | << "\t{" << std::endl 42 | << "\t\t@this.m_pBaseClass = BaseClass;" << std::endl 43 | << "\t}" << std::endl 44 | << "\t" << pszCPPBaseClassName << "@ get_BaseClass() const { return m_pBaseClass; }" << std::endl; 45 | } 46 | 47 | if( pszClassContents ) 48 | { 49 | //Output it so it's aligned with the rest of the class contents. 50 | std::stringstream contents( pszClassContents ); 51 | 52 | std::string szLine; 53 | 54 | while( std::getline( contents, szLine ) ) 55 | { 56 | stream << '\t' << szLine << std::endl; 57 | } 58 | } 59 | 60 | stream << '}' << std::endl; 61 | 62 | return stream.str(); 63 | } 64 | 65 | bool InitializeExtendClass( IASExtendAdapter& adapter, void* const pThis, const char* const pszCPPClassName, const char* const pszCPPBaseClassName ) 66 | { 67 | assert( pThis ); 68 | assert( pszCPPClassName ); 69 | 70 | auto obj = adapter.GetObject(); 71 | 72 | assert( obj ); 73 | 74 | if( !obj ) 75 | return false; 76 | 77 | const auto& typeInfo = obj.GetTypeInfo(); 78 | 79 | assert( typeInfo ); 80 | 81 | std::stringstream stream; 82 | 83 | stream << "void SetSelf( " << pszCPPClassName << "@ )"; 84 | 85 | std::string szFunction = stream.str(); 86 | 87 | bool bSuccess = false; 88 | 89 | //Initialize the self member. 90 | if( auto pFunction = typeInfo->GetMethodByDecl( szFunction.c_str() ) ) 91 | { 92 | CASOwningContext ctx( *pFunction->GetEngine() ); 93 | 94 | CASMethod method( *pFunction, ctx, *obj ); 95 | 96 | assert( method.IsValid() ); 97 | 98 | if( method.Call( CallFlag::NONE, pThis ) ) 99 | { 100 | bSuccess = true; 101 | } 102 | } 103 | 104 | //If the user has provided a baseclass type, initialize the BaseClass member. 105 | if( bSuccess && pszCPPBaseClassName ) 106 | { 107 | bSuccess = false; 108 | 109 | stream.str( "" ); 110 | 111 | stream << "void SetBaseClass( " << pszCPPBaseClassName << "@ )"; 112 | 113 | szFunction = stream.str(); 114 | 115 | if( auto pFunction = typeInfo->GetMethodByDecl( szFunction.c_str() ) ) 116 | { 117 | CASOwningContext ctx( *pFunction->GetEngine() ); 118 | 119 | CASMethod method( *pFunction, ctx, *obj ); 120 | 121 | assert( method.IsValid() ); 122 | 123 | if( method.Call( CallFlag::NONE, pThis ) ) 124 | { 125 | bSuccess = true; 126 | } 127 | } 128 | } 129 | 130 | return bSuccess; 131 | } 132 | } -------------------------------------------------------------------------------- /src/AngelscriptUtils/util/ASExtendAdapter.h: -------------------------------------------------------------------------------- 1 | #ifndef ANGELSCRIPT_UTIL_ASEXTENDADAPTER_H 2 | #define ANGELSCRIPT_UTIL_ASEXTENDADAPTER_H 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include "ASUtil.h" 10 | 11 | #include "CASObjPtr.h" 12 | 13 | class IASExtendAdapter; 14 | 15 | /** 16 | * @defgroup ASExtend Angelscript Class Extension Framework 17 | * 18 | * @{ 19 | */ 20 | 21 | namespace as 22 | { 23 | /** 24 | * Creates a class declaration for an extension class that scripts can inherit from. 25 | * @param pszClassName The class name that the class will have. 26 | * @param pszBaseClassName Class or interface to inherit from. Can be a list of classes/interfaces, separated by commas. 27 | * @param pszCPPClassName Registered name of the class that represents the C++ version of the class. Will be represented by the self member. 28 | * @param pszCPPBaseClassName Registered name of the class that provides base class method calling features. 29 | * Will be represented by the BaseClass member. 30 | * Can be null, in which case no BaseClass member is defined. 31 | * @param pszClassContents Optional. Contents to add to the class in addition to those provided by the framework. 32 | * @return String containing the class declaration. 33 | */ 34 | std::string CreateExtendBaseclassDeclaration( 35 | const char* const pszClassName, const char* const pszBaseClassName, 36 | const char* const pszCPPClassName, const char* const pszCPPBaseClassName, 37 | const char* const pszClassContents = nullptr ); 38 | 39 | /** 40 | * Initializes the extension class. 41 | * @param adapter The adapter representing the class. 42 | * @param pThis This pointer to set. Usually the same as &adapter, but could be different when using multiple inheritance. 43 | * @param pszCPPClassName Registered name of the class that represents the C++ version of the class. 44 | * @param pszCPPBaseClassName Registered name of the class that provides base class method calling features. Can be null, in which case no BaseClass member is initialized. 45 | * @return true on success, false otherwise. 46 | */ 47 | bool InitializeExtendClass( 48 | IASExtendAdapter& adapter, void* const pThis, 49 | const char* const pszCPPClassName, const char* const pszCPPBaseClassName ); 50 | 51 | /** 52 | * Creates an instance of an extension class. 53 | * @param engine Script engine. 54 | * @param typeInfo Type info for the class. 55 | * @param pszCPPClassName Registered name of the class that represents the C++ version of the class. 56 | * @param pszCPPBaseClassName Registered name of the class that provides base class method calling features. Can be null, in which case no BaseClass member is initialized. 57 | * @tparam CLASS Class type to instantiate. Must derive from IASExtendAdapter. 58 | * @return Instance, or null if an error occurred. 59 | */ 60 | template 61 | CLASS* CreateExtensionClassInstance( 62 | asIScriptEngine& engine, 63 | asITypeInfo& typeInfo, const char* const pszCPPClassName, const char* const pszCPPBaseClassName = nullptr ) 64 | { 65 | assert( pszCPPClassName ); 66 | 67 | if( auto pInstance = as::CreateObjectInstance( engine, typeInfo ) ) 68 | { 69 | auto* pCPPInstance = new CLASS( CASObjPtr( pInstance, &typeInfo, true ) ); 70 | 71 | if( as::InitializeExtendClass( *pCPPInstance, pCPPInstance, pszCPPClassName, pszCPPBaseClassName ) ) 72 | { 73 | return pCPPInstance; 74 | } 75 | 76 | delete pCPPInstance; 77 | } 78 | 79 | return nullptr; 80 | } 81 | 82 | /** 83 | * Creates an instance of an extension class. 84 | * @param engine Script engine. 85 | * @param module Script module that contains the class. 86 | * @param pszClassName Name of the script class to instantiate. 87 | * @param pszCPPClassName 88 | * @param pszCPPBaseClassName 89 | * @see CreateExtensionClassInstance( asIScriptEngine& engine, asITypeInfo& typeInfo, const char* const pszCPPClassName, const char* const pszCPPBaseClassName ) 90 | */ 91 | template 92 | CLASS* CreateExtensionClassInstance( 93 | asIScriptEngine& engine, asIScriptModule& module, 94 | const char* const pszClassName, const char* const pszCPPClassName, const char* const pszCPPBaseClassName = nullptr ) 95 | { 96 | assert( pszClassName ); 97 | 98 | const std::string szOldNS = module.GetDefaultNamespace(); 99 | 100 | const std::string szNS = as::ExtractNameFromName( pszClassName ); 101 | 102 | module.SetDefaultNamespace( szNS.c_str() ); 103 | 104 | CLASS* pInstance = nullptr; 105 | 106 | if( auto pType = module.GetTypeInfoByName( pszClassName ) ) 107 | { 108 | pInstance = CreateExtensionClassInstance( engine, *pType, pszCPPClassName, pszCPPBaseClassName ); 109 | } 110 | 111 | module.SetDefaultNamespace( szOldNS.c_str() ); 112 | 113 | return pInstance; 114 | } 115 | } 116 | 117 | /** @} */ 118 | 119 | #endif //ANGELSCRIPT_UTIL_ASEXTENDADAPTER_H -------------------------------------------------------------------------------- /src/AngelscriptUtils/util/ASLogging.cpp: -------------------------------------------------------------------------------- 1 | #include "ASLogging.h" 2 | 3 | namespace as 4 | { 5 | std::shared_ptr log; 6 | } 7 | -------------------------------------------------------------------------------- /src/AngelscriptUtils/util/ASLogging.h: -------------------------------------------------------------------------------- 1 | #ifndef ANGELSCRIPT_UTIL_ASLOGGING_H 2 | #define ANGELSCRIPT_UTIL_ASLOGGING_H 3 | 4 | #include 5 | 6 | #include 7 | 8 | #ifdef WIN32 9 | #undef VOID 10 | #undef GetObject 11 | #endif 12 | 13 | /** 14 | * @file 15 | * Provides the log global 16 | */ 17 | 18 | namespace as 19 | { 20 | /** 21 | * @brief The logger used by AngelscriptUtils. Expected to never be null 22 | * 23 | * @details The user is responsible for setting this and freeing it on program shutdown 24 | * If not provided, CASManager will create a default logger that outputs to stdout 25 | */ 26 | extern std::shared_ptr log; 27 | } 28 | 29 | #endif //ANGELSCRIPT_UTIL_ASLOGGING_H 30 | -------------------------------------------------------------------------------- /src/AngelscriptUtils/util/ASPlatform.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * 4 | * Implementations for platform specific code 5 | */ 6 | #ifdef WIN32 7 | #define WIN32_LEAN_AND_MEAN 8 | #define NOMINMAX 9 | #include 10 | #include 11 | #else 12 | #include 13 | #include 14 | #endif 15 | 16 | #include "ASPlatform.h" 17 | 18 | #ifdef WIN32 19 | void MakeDirectory( const char* pszDirectoryName ) 20 | { 21 | CreateDirectoryA( pszDirectoryName, nullptr ); 22 | } 23 | 24 | void ChangeDirectory( const char* pszDirectoryName ) 25 | { 26 | _chdir( pszDirectoryName ); 27 | } 28 | #else 29 | void MakeDirectory( const char* pszDirectoryName ) 30 | { 31 | mkdir( pszDirectoryName, S_IRWXU | S_IRWXG | S_IRWXO ); 32 | } 33 | 34 | void ChangeDirectory( const char* pszDirectoryName ) 35 | { 36 | chdir( pszDirectoryName ); 37 | } 38 | #endif 39 | -------------------------------------------------------------------------------- /src/AngelscriptUtils/util/ASPlatform.h: -------------------------------------------------------------------------------- 1 | #ifndef ANGELSCRIPT_UTIL_PLATFORM_H 2 | #define ANGELSCRIPT_UTIL_PLATFORM_H 3 | 4 | #include 5 | 6 | #ifdef WIN32 7 | #if _MSC_VER < 1900 8 | #define snprintf _snprintf 9 | #endif 10 | #endif 11 | 12 | /** 13 | * Creates a directory 14 | */ 15 | void MakeDirectory( const char* pszDirectoryName ); 16 | 17 | /** 18 | * Changes the working directory 19 | */ 20 | void ChangeDirectory( const char* pszDirectoryName ); 21 | 22 | template 23 | inline size_t _ASArraySizeof( const T( & )[ SIZE ] ) 24 | { 25 | return SIZE; 26 | } 27 | 28 | #define ASARRAYSIZE( p ) _ASArraySizeof( p ) 29 | 30 | #endif //ANGELSCRIPT_UTIL_PLATFORM_H 31 | -------------------------------------------------------------------------------- /src/AngelscriptUtils/util/CASBaseClass.h: -------------------------------------------------------------------------------- 1 | #ifndef ANGELSCRIPT_CASBASECLASS_H 2 | #define ANGELSCRIPT_CASBASECLASS_H 3 | 4 | #include 5 | 6 | /** 7 | * @defgroup ASBaseClass Angelscript Base classes 8 | * 9 | * @{ 10 | */ 11 | 12 | /** 13 | * Base class for Angelscript classes that require one. 14 | */ 15 | class CASBaseClass 16 | { 17 | public: 18 | CASBaseClass() = default; 19 | CASBaseClass( const CASBaseClass& other ) = default; 20 | CASBaseClass& operator=( const CASBaseClass& other ) = default; 21 | ~CASBaseClass() = default; 22 | }; 23 | 24 | /** 25 | * Base class for all Angelscript classes that are reference counted 26 | */ 27 | class CASRefCountedBaseClass : public CASBaseClass 28 | { 29 | public: 30 | /** 31 | * Constructor. 32 | */ 33 | CASRefCountedBaseClass() 34 | : CASBaseClass() 35 | , m_iRefCount( 1 ) 36 | { 37 | } 38 | 39 | /** 40 | * Copy constructor. 41 | */ 42 | CASRefCountedBaseClass( const CASRefCountedBaseClass& other ) 43 | : CASBaseClass( other ) 44 | , m_iRefCount( 1 ) 45 | { 46 | } 47 | 48 | CASRefCountedBaseClass& operator=( const CASRefCountedBaseClass& other ) = default; 49 | 50 | ~CASRefCountedBaseClass() = default; 51 | 52 | /** 53 | * @return The reference count. 54 | */ 55 | int GetRefCount() const { return m_iRefCount; } 56 | 57 | /** 58 | * Adds a reference. 59 | */ 60 | void AddRef() const; 61 | 62 | protected: 63 | /** 64 | * Releases a reference. 65 | * @return true if the reference count has become 0 66 | */ 67 | bool InternalRelease() const; 68 | 69 | protected: 70 | mutable int m_iRefCount; 71 | }; 72 | 73 | inline void CASRefCountedBaseClass::AddRef() const 74 | { 75 | ++m_iRefCount; 76 | } 77 | 78 | inline bool CASRefCountedBaseClass::InternalRelease() const 79 | { 80 | return !--m_iRefCount; 81 | } 82 | 83 | /** 84 | * Base class for all Angelscript classes that are reference counted and are used acrosss threads 85 | */ 86 | class CASAtomicRefCountedBaseClass : public CASRefCountedBaseClass 87 | { 88 | public: 89 | CASAtomicRefCountedBaseClass() = default; 90 | CASAtomicRefCountedBaseClass( const CASAtomicRefCountedBaseClass& other ) = default; 91 | CASAtomicRefCountedBaseClass& operator=( const CASAtomicRefCountedBaseClass& other ) = default; 92 | ~CASAtomicRefCountedBaseClass() = default; 93 | 94 | /** 95 | * @copydoc CASRefCountedBaseClass::AddRef() const 96 | * Thread-safe. 97 | */ 98 | void AddRef() const; 99 | 100 | protected: 101 | /** 102 | * @copydoc CASRefCountedBaseClass::InternalRelease() const 103 | * Thread-safe. 104 | */ 105 | bool InternalRelease() const; 106 | }; 107 | 108 | inline void CASAtomicRefCountedBaseClass::AddRef() const 109 | { 110 | asAtomicInc( m_iRefCount ); 111 | } 112 | 113 | inline bool CASAtomicRefCountedBaseClass::InternalRelease() const 114 | { 115 | return !asAtomicDec( m_iRefCount ); 116 | } 117 | 118 | /** 119 | * Garbage collected base class 120 | * Pass in either CASRefCountedBaseClass or CASAtomicRefCountedBaseClass as the base class 121 | */ 122 | template 123 | class CASGCBaseClass : public BASECLASS 124 | { 125 | public: 126 | CASGCBaseClass() = default; 127 | CASGCBaseClass( const CASGCBaseClass& other ) = default; 128 | CASGCBaseClass& operator=( const CASGCBaseClass& other ) = default; 129 | ~CASGCBaseClass() = default; 130 | 131 | /** 132 | * @return The garbage collector flag. 133 | */ 134 | bool GetGCFlag() const { return m_fGCFlag; } 135 | 136 | /** 137 | * Sets the garbage collector flag. 138 | */ 139 | void SetGCFlag() const { m_fGCFlag = true; } 140 | 141 | /** 142 | * Adds a reference and clears the garbage collector flag. 143 | */ 144 | void AddRef() const 145 | { 146 | m_fGCFlag = false; 147 | 148 | BASECLASS::AddRef(); 149 | } 150 | 151 | protected: 152 | /** 153 | * Releases a reference and clears the garbage collector flag. 154 | */ 155 | bool InternalRelease() const 156 | { 157 | m_fGCFlag = false; 158 | 159 | return BASECLASS::InternalRelease(); 160 | } 161 | 162 | private: 163 | mutable bool m_fGCFlag = false; 164 | }; 165 | 166 | /** 167 | * Base class for garbage collected classes. 168 | */ 169 | typedef CASGCBaseClass CASGCRefCountedBaseClass; 170 | 171 | /** 172 | * Base class for thread-safe garbage collected classes. 173 | */ 174 | typedef CASGCBaseClass CASGCAtomicRefCountedBaseClass; 175 | 176 | namespace as 177 | { 178 | /** 179 | * Registers a ref counted class's ref counting behaviors. 180 | * @param pEngine Script engine. 181 | * @param pszObjectName Object name. 182 | */ 183 | template 184 | void RegisterRefCountedBaseClass( asIScriptEngine* pEngine, const char* pszObjectName ) 185 | { 186 | pEngine->RegisterObjectBehaviour( 187 | pszObjectName, asBEHAVE_ADDREF, "void AddRef()", 188 | asMETHODPR( CLASS, AddRef, ( ) const, void ), asCALL_THISCALL ); 189 | 190 | pEngine->RegisterObjectBehaviour( 191 | pszObjectName, asBEHAVE_RELEASE, "void Release()", 192 | asMETHODPR( CLASS, Release, ( ) const, void ), asCALL_THISCALL ); 193 | } 194 | 195 | /** 196 | * Registers a garbage collected, ref counted class's ref counting and gc behaviors. 197 | * @param pEngine Script engine. 198 | * @param pszObjectName Object name. 199 | */ 200 | template 201 | void RegisterGCRefCountedBaseClass( asIScriptEngine* pEngine, const char* pszObjectName ) 202 | { 203 | RegisterRefCountedBaseClass( pEngine, pszObjectName ); 204 | 205 | pEngine->RegisterObjectBehaviour( 206 | pszObjectName, asBEHAVE_GETREFCOUNT, "int GetRefCount() const", 207 | asMETHODPR( CLASS, GetRefCount, ( ) const, int ), asCALL_THISCALL ); 208 | 209 | pEngine->RegisterObjectBehaviour( 210 | pszObjectName, asBEHAVE_GETGCFLAG, "bool GetGCFlag() const", 211 | asMETHODPR( CLASS, GetGCFlag, ( ) const, bool ), asCALL_THISCALL ); 212 | 213 | pEngine->RegisterObjectBehaviour( 214 | pszObjectName, asBEHAVE_SETGCFLAG, "void SetGCFlag()", 215 | asMETHODPR( CLASS, SetGCFlag, ( ) const, void ), asCALL_THISCALL ); 216 | 217 | pEngine->RegisterObjectBehaviour( 218 | pszObjectName, asBEHAVE_ENUMREFS, "void EnumReferences(int& in)", 219 | asMETHOD( CLASS, EnumReferences ), asCALL_THISCALL ); 220 | 221 | pEngine->RegisterObjectBehaviour( 222 | pszObjectName, asBEHAVE_RELEASEREFS, "void ReleaseReferences(int& in)", 223 | asMETHOD( CLASS, ReleaseReferences ), asCALL_THISCALL ); 224 | } 225 | } 226 | 227 | /** @} */ 228 | 229 | #endif //ANGELSCRIPT_CASBASECLASS_H 230 | -------------------------------------------------------------------------------- /src/AngelscriptUtils/util/CASExtendAdapter.h: -------------------------------------------------------------------------------- 1 | #ifndef ANGELSCRIPT_UTIL_CASEXTENDADAPTER_H 2 | #define ANGELSCRIPT_UTIL_CASEXTENDADAPTER_H 3 | 4 | #include 5 | 6 | #include "IASExtendAdapter.h" 7 | 8 | #include "CASObjPtr.h" 9 | 10 | #include "AngelscriptUtils/wrapper/ASCallable.h" 11 | 12 | /** 13 | * @addtogroup ASExtend 14 | * 15 | * @{ 16 | */ 17 | 18 | /** 19 | * Class used to adapt C++ classes for extension in Angelscript. 20 | * @tparam BASECLASS C++ class to extend. Should be a class with at least one virtual function. 21 | * @tparam DERIVEDCLASS C++ class that will be instantiated. Used to call object methods correctly. 22 | */ 23 | template 24 | class CASExtendAdapter : public BASECLASS, public IASExtendAdapter 25 | { 26 | public: 27 | typedef BASECLASS BaseClass; 28 | typedef CASExtendAdapter ThisClass; 29 | typedef DERIVEDCLASS DerivedClass; 30 | 31 | public: 32 | /** 33 | * Constructor. 34 | * @param object Script object that extends this object. 35 | */ 36 | CASExtendAdapter( CASObjPtr object ) 37 | : BASECLASS() 38 | , m_Object( object ) 39 | { 40 | assert( object ); 41 | } 42 | 43 | /** 44 | * Constructor. 45 | * @param object Script object that extends this object. 46 | * @param args Arguments for the baseclass constructor. 47 | * @tparam ARGS Argument types for the baseclass constructor. 48 | */ 49 | template 50 | CASExtendAdapter( CASObjPtr object, ARGS&&... args ) 51 | : BASECLASS( std::move( args )... ) 52 | , m_Object( object ) 53 | { 54 | assert( object ); 55 | } 56 | 57 | /** 58 | * @return The object instance. 59 | */ 60 | const CASObjPtr& GetObject() const override final 61 | { 62 | return m_Object; 63 | } 64 | 65 | /** 66 | * @copydoc GetObject() const 67 | */ 68 | CASObjPtr GetObject() override final 69 | { 70 | return m_Object; 71 | } 72 | 73 | private: 74 | CASObjPtr m_Object; 75 | 76 | private: 77 | //TODO: consider adding support for copying. 78 | CASExtendAdapter( const CASExtendAdapter& ) = delete; 79 | CASExtendAdapter& operator=( const CASExtendAdapter& ) = delete; 80 | }; 81 | 82 | /* 83 | * Helper macros. 84 | */ 85 | 86 | /** 87 | * Calls a method that has a different C++ method name, and returns non-void. 88 | * @param retType Return type. 89 | * @param methodName Script method name to call. 90 | * @param baseMethodName C++ method name to call. 91 | * @param pszParams Script method parameters. 92 | * @param ... Arguments to pass. 93 | */ 94 | #define CALL_EXTEND_FUNC_RET_DIFFFUNC( retType, methodName, baseMethodName, pszParams, ... ) \ 95 | retType result = retType(); \ 96 | \ 97 | if( auto pFunction = GetObject().GetTypeInfo()->GetMethodByDecl( #retType " " #methodName pszParams ) ) \ 98 | { \ 99 | CASOwningContext ctx( *pFunction->GetEngine() ); \ 100 | \ 101 | CASMethod method( *pFunction, ctx, GetObject().Get() ); \ 102 | \ 103 | if( method.Call( CallFlag::NONE, ##__VA_ARGS__ ) ) \ 104 | { \ 105 | method.GetReturnValue( &result ); \ 106 | } \ 107 | } \ 108 | else \ 109 | { \ 110 | result = baseMethodName( __VA_ARGS__ ); \ 111 | } \ 112 | \ 113 | return result 114 | 115 | /** 116 | * Calls a method, and returns non-void. 117 | * @param retType Return type. 118 | * @param methodName Script or C++ method name to call. 119 | * @param pszParams Script method parameters. 120 | * @param ... Arguments to pass. 121 | */ 122 | #define CALL_EXTEND_FUNC_RET( retType, methodName, pszParams, ... ) \ 123 | CALL_EXTEND_FUNC_RET_DIFFFUNC( retType, methodName, BaseClass::methodName, pszParams, ##__VA_ARGS__ ) 124 | 125 | /** 126 | * Calls a method that has a different C++ method name. 127 | * @param methodName Script method name to call. 128 | * @param baseMethodName C++ method name to call. 129 | * @param pszParams Script method parameters. 130 | * @param ... Arguments to pass. 131 | */ 132 | #define CALL_EXTEND_FUNC_DIFFFUNC( methodName, baseMethodName, pszParams, ... ) \ 133 | if( auto pFunction = GetObject().GetTypeInfo()->GetMethodByDecl( "void " #methodName pszParams ) ) \ 134 | { \ 135 | as::Call( GetObject().Get(), pFunction, ##__VA_ARGS__ ); \ 136 | } \ 137 | else \ 138 | { \ 139 | baseMethodName( __VA_ARGS__ ); \ 140 | } 141 | 142 | /** 143 | * Calls a method. 144 | * @param methodName Script or C++ method name to call. 145 | * @param pszParams Script method parameters. 146 | * @param ... Arguments to pass. 147 | */ 148 | #define CALL_EXTEND_FUNC( methodName, pszParams, ... ) \ 149 | CALL_EXTEND_FUNC_DIFFFUNC( methodName, BaseClass::methodName, pszParams, ##__VA_ARGS__ ) 150 | 151 | /** @} */ 152 | 153 | #endif //ANGELSCRIPT_UTIL_CASEXTENDADAPTER_H -------------------------------------------------------------------------------- /src/AngelscriptUtils/util/CASObjPtr.h: -------------------------------------------------------------------------------- 1 | #ifndef ANGELSCRIPT_UTIL_CASOBJPTR_H 2 | #define ANGELSCRIPT_UTIL_CASOBJPTR_H 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include "CASRefPtr.h" 10 | 11 | /** 12 | * @addtogroup ASUtil 13 | * 14 | * @{ 15 | */ 16 | 17 | /** 18 | * Smart pointer for script objects. 19 | */ 20 | class CASObjPtr final 21 | { 22 | public: 23 | /** 24 | * Default constructor. 25 | */ 26 | CASObjPtr() = default; 27 | 28 | /** 29 | * Initializing constructor. 30 | * @param pThis This pointer. Can be null. 31 | * @param typeInfo Type info. Must be valid if pThis is not null. 32 | * @param bTransferOwnership Whether to transfer ownership or not. 33 | * @see as::SetObjPointer 34 | */ 35 | CASObjPtr( void* pThis, CASRefPtr typeInfo, const bool bTransferOwnership = false ); 36 | 37 | /** 38 | * Copy constructor. 39 | */ 40 | CASObjPtr( const CASObjPtr& other ); 41 | 42 | /** 43 | * Assignment operator. 44 | */ 45 | CASObjPtr& operator=( const CASObjPtr& other ); 46 | 47 | /** 48 | * Move constructor. 49 | */ 50 | CASObjPtr( CASObjPtr&& other ); 51 | 52 | /** 53 | * Move assignment operator. 54 | */ 55 | CASObjPtr& operator=( CASObjPtr&& other ); 56 | 57 | /** 58 | * Destructor. 59 | */ 60 | ~CASObjPtr(); 61 | 62 | /** 63 | * @return Whether this points to an object or not. 64 | */ 65 | operator bool() const; 66 | 67 | /** 68 | * @return Pointer to the object. The reference count is not incremented. 69 | */ 70 | const void* Get() const; 71 | 72 | /** 73 | * @copydoc Get() const 74 | */ 75 | void* Get(); 76 | 77 | /** 78 | * @return Type info. 79 | */ 80 | const CASRefPtr& GetTypeInfo() const; 81 | 82 | /** 83 | * @copydoc GetTypeInfo() const 84 | */ 85 | CASRefPtr GetTypeInfo(); 86 | 87 | /** 88 | * Releases the reference held by this pointer. The reference count is unchanged. 89 | */ 90 | void* ReleaseOwnership(); 91 | 92 | /** 93 | * Releases the reference held by this pointer. The reference count is decremented. 94 | */ 95 | void Reset(); 96 | 97 | /** 98 | * Sets the object and type info. 99 | * @param pThis This pointer. Can be null. 100 | * @param typeInfo Type info. Must be valid if pThis is not null. 101 | * @param bTransferOwnership Whether to transfer ownership or not. 102 | * @see as::SetObjPointer 103 | */ 104 | void Set( void* pThis, CASRefPtr typeInfo, const bool bTransferOwnership = false ); 105 | 106 | /** 107 | * Operator dereference. 108 | */ 109 | const void* operator*() const 110 | { 111 | return m_pThis; 112 | } 113 | 114 | /** 115 | * @copydoc operator*() const 116 | */ 117 | void* operator*() 118 | { 119 | return m_pThis; 120 | } 121 | 122 | /** 123 | * Operator const void*. 124 | */ 125 | operator const void*() const 126 | { 127 | return m_pThis; 128 | } 129 | 130 | /** 131 | * Operator void*. 132 | */ 133 | operator void*() 134 | { 135 | return m_pThis; 136 | } 137 | 138 | private: 139 | void* m_pThis = nullptr; 140 | CASRefPtr m_TypeInfo; 141 | }; 142 | 143 | inline CASObjPtr::CASObjPtr( void* pThis, CASRefPtr typeInfo, const bool bTransferOwnership ) 144 | { 145 | Set( pThis, typeInfo, bTransferOwnership ); 146 | } 147 | 148 | inline CASObjPtr::CASObjPtr( const CASObjPtr& other ) 149 | : m_pThis( nullptr ) 150 | , m_TypeInfo( other.m_TypeInfo ) 151 | { 152 | //The this pointer can't be valid without typeinfo being valid as well. 153 | assert( !other.m_pThis || m_TypeInfo ); 154 | 155 | if( other.m_pThis ) 156 | { 157 | as::SetObjPointer( m_pThis, other.m_pThis, *m_TypeInfo ); 158 | } 159 | } 160 | 161 | inline CASObjPtr& CASObjPtr::operator=( const CASObjPtr& other ) 162 | { 163 | if( this != &other ) 164 | { 165 | Reset(); 166 | 167 | if( other.m_pThis ) 168 | { 169 | m_TypeInfo = other.m_TypeInfo; 170 | 171 | as::SetObjPointer( m_pThis, other.m_pThis, *m_TypeInfo ); 172 | } 173 | } 174 | 175 | return *this; 176 | } 177 | 178 | inline CASObjPtr::CASObjPtr( CASObjPtr&& other ) 179 | : m_pThis( other.m_pThis ) 180 | , m_TypeInfo( std::move( other.m_TypeInfo ) ) 181 | { 182 | other.m_pThis = nullptr; 183 | } 184 | 185 | inline CASObjPtr& CASObjPtr::operator=( CASObjPtr&& other ) 186 | { 187 | if( this != &other ) 188 | { 189 | Reset(); 190 | std::swap( m_pThis, other.m_pThis ); 191 | std::swap( m_TypeInfo, other.m_TypeInfo ); 192 | } 193 | 194 | return *this; 195 | } 196 | 197 | inline CASObjPtr::~CASObjPtr() 198 | { 199 | Reset(); 200 | } 201 | 202 | inline CASObjPtr::operator bool() const 203 | { 204 | return m_pThis != nullptr; 205 | } 206 | 207 | inline const void* CASObjPtr::Get() const 208 | { 209 | return m_pThis; 210 | } 211 | 212 | inline void* CASObjPtr::Get() 213 | { 214 | return m_pThis; 215 | } 216 | 217 | inline const CASRefPtr& CASObjPtr::GetTypeInfo() const 218 | { 219 | return m_TypeInfo; 220 | } 221 | 222 | inline CASRefPtr CASObjPtr::GetTypeInfo() 223 | { 224 | return m_TypeInfo; 225 | } 226 | 227 | inline void* CASObjPtr::ReleaseOwnership() 228 | { 229 | auto pThis = m_pThis; 230 | 231 | m_pThis = nullptr; 232 | 233 | return pThis; 234 | } 235 | 236 | inline void CASObjPtr::Reset() 237 | { 238 | //The this pointer can't be valid without typeinfo being valid as well. 239 | assert( !m_pThis || m_TypeInfo ); 240 | 241 | if( m_pThis ) 242 | { 243 | as::SetObjPointer( m_pThis, nullptr, *m_TypeInfo ); 244 | 245 | m_TypeInfo = nullptr; 246 | } 247 | } 248 | 249 | inline void CASObjPtr::Set( void* pThis, CASRefPtr typeInfo, const bool bTransferOwnership ) 250 | { 251 | Reset(); 252 | 253 | //TODO: should the type info pointer be stored even if this is null? 254 | 255 | if( pThis ) 256 | { 257 | if( !typeInfo ) 258 | { 259 | assert( false ); 260 | } 261 | else 262 | { 263 | m_TypeInfo = std::move( typeInfo ); 264 | as::SetObjPointer( m_pThis, pThis, *m_TypeInfo, bTransferOwnership ); 265 | } 266 | } 267 | } 268 | 269 | /** @} */ 270 | 271 | #endif //ANGELSCRIPT_UTIL_CASOBJPTR_H -------------------------------------------------------------------------------- /src/AngelscriptUtils/util/CASRefPtr.h: -------------------------------------------------------------------------------- 1 | #ifndef ANGELSCRIPT_UTIL_CASREFPTR_H 2 | #define ANGELSCRIPT_UTIL_CASREFPTR_H 3 | 4 | #include 5 | 6 | #include "ASUtil.h" 7 | 8 | /** 9 | * @addtogroup ASUtil 10 | * 11 | * @{ 12 | */ 13 | 14 | /** 15 | * Smart pointer for Angelscript objects. 16 | * @tparam T Object type. 17 | * @tparam ADAPTER Adapter that implements static AddRef and Release functions for the given object type. 18 | */ 19 | template> 20 | class CASRefPtr final 21 | { 22 | public: 23 | typedef T Type_t; 24 | typedef ADAPTER Adapter_t; 25 | 26 | public: 27 | /** 28 | * Sets the given pointer to the given object. Uses this class's template parameters. 29 | * @see as::SetRefPointer 30 | */ 31 | static T* Set( T*& pPtr, T* const pSourcePtr, const bool bTransferOwnership = false ); 32 | 33 | /** 34 | * Default constructor. 35 | */ 36 | CASRefPtr(); 37 | 38 | /** 39 | * Initializing constructor. 40 | * @param pPointer Object to set. Can be null. 41 | * @param bTransferOwnership Whether to transfer ownership or not. 42 | * @see as::SetRefPointer 43 | */ 44 | CASRefPtr( T* pPointer, const bool bTransferOwnership = false ); 45 | 46 | /** 47 | * Assignment operator. 48 | */ 49 | CASRefPtr& operator=( T* const pPtr ); 50 | 51 | /** 52 | * Copy constructor. 53 | */ 54 | CASRefPtr( const CASRefPtr& other ); 55 | 56 | /** 57 | * Assignment operator. 58 | */ 59 | CASRefPtr& operator=( const CASRefPtr& other ); 60 | 61 | /** 62 | * Move constructor. 63 | */ 64 | CASRefPtr( CASRefPtr&& other ); 65 | 66 | /** 67 | * Move assignment operator. 68 | */ 69 | CASRefPtr& operator=( CASRefPtr&& other ); 70 | 71 | /** 72 | * Destructor. 73 | */ 74 | ~CASRefPtr(); 75 | 76 | /** 77 | * @return Whether this points to an object or not. 78 | */ 79 | operator bool() const; 80 | 81 | /** 82 | * @return Pointer to the object. The reference count is not incremented. 83 | */ 84 | const T* Get() const; 85 | 86 | /** 87 | * @copydoc Get() const 88 | */ 89 | T* Get(); 90 | 91 | /** 92 | * Releases the reference held by this pointer. The reference count is unchanged. 93 | */ 94 | T* ReleaseOwnership(); 95 | 96 | /** 97 | * Releases the reference held by this pointer. The reference count is decremented. 98 | */ 99 | void Reset(); 100 | 101 | /** 102 | * Sets the pointer to the given object. If this pointer is currently holding a reference to another object, that object is released. 103 | * @param pSourcePtr Object to point to. Can be null. 104 | * @param bTransferOwnership Whether to transfer ownership or not. 105 | * @return Pointer to the object. 106 | * @see as::SetRefPointer 107 | */ 108 | T* Set( T* const pSourcePtr, const bool bTransferOwnership = false ); 109 | 110 | /** 111 | * Operator dereference. 112 | */ 113 | const T& operator*() const 114 | { 115 | return *m_pPointer; 116 | } 117 | 118 | /** 119 | * @copydoc operator*() const 120 | */ 121 | T& operator*() 122 | { 123 | return *m_pPointer; 124 | } 125 | 126 | /** 127 | * Operator class member. 128 | */ 129 | const T* operator->() const 130 | { 131 | return m_pPointer; 132 | } 133 | 134 | /** 135 | * @copydoc operator->() const 136 | */ 137 | T* operator->() 138 | { 139 | return m_pPointer; 140 | } 141 | 142 | /** 143 | * Operator const T*. 144 | */ 145 | operator const T*() const 146 | { 147 | return m_pPointer; 148 | } 149 | 150 | /** 151 | * Operator T*. 152 | */ 153 | operator T*() 154 | { 155 | return m_pPointer; 156 | } 157 | 158 | private: 159 | T* m_pPointer = nullptr; 160 | }; 161 | 162 | template 163 | T* CASRefPtr::Set( T*& pPtr, T* const pSourcePtr, const bool bTransferOwnership ) 164 | { 165 | return as::SetRefPointer( pPtr, pSourcePtr, bTransferOwnership ); 166 | } 167 | 168 | template 169 | CASRefPtr::CASRefPtr() 170 | { 171 | } 172 | 173 | template 174 | CASRefPtr::CASRefPtr( T* pPointer, const bool bTransferOwnership ) 175 | { 176 | Set( m_pPointer, pPointer, bTransferOwnership ); 177 | } 178 | 179 | template 180 | CASRefPtr& CASRefPtr::operator=( T* const pPtr ) 181 | { 182 | if( m_pPointer != pPtr ) 183 | { 184 | Set( m_pPointer, pPtr, false ); 185 | } 186 | 187 | return *this; 188 | } 189 | 190 | template 191 | CASRefPtr::CASRefPtr( const CASRefPtr& other ) 192 | { 193 | Set( m_pPointer, other.m_pPointer, false ); 194 | } 195 | 196 | template 197 | CASRefPtr& CASRefPtr::operator=( const CASRefPtr& other ) 198 | { 199 | if( this != &other ) 200 | { 201 | Set( m_pPointer, other.m_pPointer, false ); 202 | } 203 | 204 | return *this; 205 | } 206 | 207 | template 208 | CASRefPtr::CASRefPtr( CASRefPtr&& other ) 209 | : m_pPointer( other.m_pPointer ) 210 | { 211 | other.m_pPointer = nullptr; 212 | } 213 | 214 | template 215 | CASRefPtr& CASRefPtr::operator=( CASRefPtr&& other ) 216 | { 217 | if( this != &other ) 218 | { 219 | Set( m_pPointer, other.m_pPointer, true ); 220 | other.m_pPointer = nullptr; 221 | } 222 | 223 | return *this; 224 | } 225 | 226 | template 227 | CASRefPtr::~CASRefPtr() 228 | { 229 | Reset(); 230 | } 231 | 232 | template 233 | CASRefPtr::operator bool() const 234 | { 235 | return m_pPointer != nullptr; 236 | } 237 | 238 | template 239 | const T* CASRefPtr::Get() const 240 | { 241 | return m_pPointer; 242 | } 243 | 244 | template 245 | T* CASRefPtr::Get() 246 | { 247 | return m_pPointer; 248 | } 249 | 250 | template 251 | T* CASRefPtr::ReleaseOwnership() 252 | { 253 | if( !m_pPointer ) 254 | return nullptr; 255 | 256 | auto pPointer = m_pPointer; 257 | 258 | m_pPointer = nullptr; 259 | 260 | return pPointer; 261 | } 262 | 263 | template 264 | void CASRefPtr::Reset() 265 | { 266 | Set( m_pPointer, nullptr, false ); 267 | } 268 | 269 | template 270 | T* CASRefPtr::Set( T* const pSourcePtr, const bool bTransferOwnership ) 271 | { 272 | return Set( m_pPointer, pSourcePtr, bTransferOwnership ); 273 | } 274 | 275 | /** @} */ 276 | 277 | #endif //ANGELSCRIPT_UTIL_CASREFPTR_H -------------------------------------------------------------------------------- /src/AngelscriptUtils/util/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_sources( 2 | ASExtendAdapter.h 3 | ASExtendAdapter.cpp 4 | ASLogging.h 5 | ASLogging.cpp 6 | ASPlatform.cpp 7 | ASPlatform.h 8 | ASUtil.h 9 | ASUtil.cpp 10 | ContextUtils.h 11 | ContextUtils.cpp 12 | CASBaseClass.h 13 | CASExtendAdapter.h 14 | CASRefPtr.h 15 | CASObjPtr.h 16 | IASExtendAdapter.h 17 | StringUtils.h 18 | ) 19 | 20 | add_includes( 21 | ASExtendAdapter.h 22 | ASLogging.h 23 | ASPlatform.h 24 | ASUtil.h 25 | ContextUtils.h 26 | CASBaseClass.h 27 | CASExtendAdapter.h 28 | CASRefPtr.h 29 | CASObjPtr.h 30 | IASExtendAdapter.h 31 | StringUtils.h 32 | ) -------------------------------------------------------------------------------- /src/AngelscriptUtils/util/ContextUtils.h: -------------------------------------------------------------------------------- 1 | #ifndef UTIL_CONTEXTUTILS_H 2 | #define UTIL_CONTEXTUTILS_H 3 | 4 | #include 5 | 6 | #include "AngelscriptUtils/wrapper/CASArguments.h" 7 | 8 | /** 9 | * @addtogroup ASContext 10 | * 11 | * @{ 12 | */ 13 | 14 | namespace ctx 15 | { 16 | /** 17 | * Wrapper type used to pass around va_list. On some platforms va_list isn't a simple pointer, so this solves type issues. 18 | */ 19 | struct VAList final 20 | { 21 | va_list list; 22 | }; 23 | 24 | /** 25 | * Sets arguments for a function call. 26 | * @param targetFunc Target function. 27 | * @param context Context. 28 | * @param arguments List of arguments. 29 | * @return true on success, false otherwise. 30 | */ 31 | bool SetArguments( const asIScriptFunction& targetFunc, asIScriptContext& context, const CASArguments& arguments ); 32 | 33 | /** 34 | * Sets arguments for a function call. 35 | * @param targetFunc Target function. 36 | * @param context Context. 37 | * @param list Pointer to the arguments. 38 | * @return true on success, false otherwise. 39 | */ 40 | bool SetArguments( const asIScriptFunction& targetFunc, asIScriptContext& context, va_list list ); 41 | 42 | /** 43 | * Sets an argument on arg. Determines whether it's a primitive or object argument. 44 | * @param engine Script engine. 45 | * @param pData Data to copy. 46 | * @param iTypeId Type Id. 47 | * @param arg Argument to set. 48 | * @return true on success, false otherwise. 49 | */ 50 | bool SetArgument( asIScriptEngine& engine, void* pData, int iTypeId, CASArgument& arg ); 51 | 52 | /** 53 | * Sets an argument on the context, taking the argument from a CASArgument. 54 | * @param engine Script engine. 55 | * @param targetFunc Target function. 56 | * @param context Context. 57 | * @param uiIndex Argument index. 58 | * @param arg The argument. 59 | * @return true on success, false otherwise. 60 | */ 61 | bool SetContextArgument( asIScriptEngine& engine, const asIScriptFunction& targetFunc, asIScriptContext& context, const asUINT uiIndex, const CASArgument& arg ); 62 | 63 | /** 64 | * Sets an argument on the context, taking the argument from varargs. 65 | * @param engine Script engine. 66 | * @param targetFunc Target function. 67 | * @param context Context. 68 | * @param uiIndex Argument index. 69 | * @param list Pointer to the argument. 70 | * @return true on success, false otherwise. 71 | */ 72 | bool SetContextArgument( asIScriptEngine& engine, const asIScriptFunction& targetFunc, asIScriptContext& context, const asUINT uiIndex, VAList& list ); 73 | 74 | /** 75 | * Sets an argument on the context, taking the argument from an ArgumentValue_t. 76 | * @param engine Script engine. 77 | * @param targetFunc Target function. 78 | * @param context Context. 79 | * @param uiIndex Argument index. 80 | * @param iSourceTypeId Type id of the argument. 81 | * @param value Value to set. 82 | * @param bAllowPrimitiveReferences Indicates whether primitive type arguments taken by reference use pValue or &qword. 83 | * @return true on success, false otherwise. 84 | */ 85 | bool SetContextArgument( asIScriptEngine& engine, const asIScriptFunction& targetFunc, asIScriptContext& context, 86 | const asUINT uiIndex, int iSourceTypeId, const ArgumentValue& value, bool bAllowPrimitiveReferences ); 87 | 88 | /** 89 | * Gets the argument of type iTypeId from the stack, and stores it in value 90 | * @param value Value to store the result in. 91 | * @param iTypeId Type Id of the value. 92 | * @param uiTMFlags A combination of asETypeModifiers, or asTM_NONE. 93 | * @param list Pointer to the argument. 94 | * @param[ in ] puiObjFlags Optional. Object flags. Must be set if pOutArgType is set. 95 | * @param[ out ] pOutArgType Optional. Argument type. 96 | * @return true on success, false otherwise. 97 | */ 98 | bool GetArgumentFromVarargs( ArgumentValue& value, int iTypeId, asDWORD uiTMFlags, VAList& list, asDWORD* puiObjFlags = nullptr, ArgType::ArgType* pOutArgType = nullptr ); 99 | 100 | /** 101 | * Converts the input argument to either an asQWORD or double. 102 | * iType is either asTYPEID_UINT64 or asTYPEID_DOUBLE. 103 | * @param arg Argument to convert. 104 | * @param uiValue The converted value, as an integer. 105 | * @param flValue The converted value, as a float. 106 | * @return true on success, false if conversion failed. 107 | */ 108 | bool ConvertInputArgToLargest( const CASArgument& arg, asINT64& uiValue, double& flValue ); 109 | 110 | /** 111 | * @see ConvertInputArgToLargest( const CASArgument* const pArg, asINT64& uiValue, double& flValue ) 112 | */ 113 | bool ConvertInputArgToLargest( int iTypeId, const ArgumentValue& value, asINT64& uiValue, double& flValue ); 114 | 115 | /** 116 | * Gets the argument type from a type id and object flags. 117 | * @param iTypeId Type id. 118 | * @param uiObjFlags Object flags. 119 | * @return Argument type. 120 | */ 121 | ArgType::ArgType ArgumentTypeFromTypeId( const int iTypeId, const asDWORD uiObjFlags ); 122 | 123 | /** 124 | * Converts an enum to a primitive type. 125 | * @param arg Argument to convert. 126 | * @param iTypeId Type Id. 127 | * @param outValue Converted value. 128 | * @return true on success, false otherwise. 129 | */ 130 | bool ConvertEnumToPrimitive( const CASArgument& arg, const int iTypeId, ArgumentValue& outValue ); 131 | 132 | /** 133 | * Converts a primitive type to an enum. 134 | * @param arg Argument to convert. 135 | * @param outValue Converted value. 136 | * @return true on success, false otherwise. 137 | */ 138 | bool ConvertPrimitiveToEnum( const CASArgument& arg, ArgumentValue& outValue ); 139 | 140 | /** 141 | * Tries to set the given data on the given value. 142 | * @param pData Data to copy. 143 | * @param iTypeId Type Id of the pData instance. 144 | * @param arg Argument to set. 145 | * @param[ out ] bOutWasPrimitive Whether the value was a primitive type or not. 146 | * @return true on success, false otherwise. 147 | */ 148 | bool SetPrimitiveArgument( void* pData, int iTypeId, CASArgument& arg, bool& bOutWasPrimitive ); 149 | 150 | /** 151 | * Tries to set the given data on the given value. 152 | * @param pData Data to copy. 153 | * @param iTypeId Type Id of the pData instance. 154 | * @param value Value to set. 155 | * @param[ out ] bOutWasPrimitive Whether the value was a primitive type or not. 156 | * @return true on success, false otherwise. 157 | */ 158 | bool SetPrimitiveArgument( void* pData, int iTypeId, ArgumentValue& value, bool& bOutWasPrimitive ); 159 | 160 | /** 161 | * Sets an object argument on the given argument. 162 | * @param engine Script engine. 163 | * @param pObject Object to copy or addref. 164 | * @param iTypeId Type Id. 165 | * @param arg Argument to set. 166 | * @return true on success, false otherwise. 167 | */ 168 | bool SetObjectArgument( asIScriptEngine& engine, void* pObject, int iTypeId, CASArgument& arg ); 169 | 170 | /** 171 | * Convenience method for when you don't want to get return type info yourself. 172 | * @param context Context. 173 | * @param func Function whose return type will be used. 174 | * @param retVal Return value. 175 | * @param[ out ] uiOutFlags Optional. Return type flags. 176 | * @return true on success, false otherwise. 177 | * @see GetReturnValue( asIScriptContext& context, int iTypeId, asDWORD uiFlags, CASArgument& retVal ) 178 | */ 179 | bool GetReturnValue( asIScriptContext& context, const asIScriptFunction& func, CASArgument& retVal, asDWORD* uiOutFlags = nullptr ); 180 | 181 | /** 182 | * Gets the return value from the context according to the given return value type. 183 | * @param context Context. 184 | * @param iTypeId Type id of the return value. 185 | * @param uiFlags Type flags. 186 | * @param retVal Return value. 187 | * @return true on success, false otherwise. 188 | */ 189 | bool GetReturnValue( asIScriptContext& context, int iTypeId, asDWORD uiFlags, CASArgument& retVal ); 190 | 191 | /** 192 | * Gets the return value from the context according to the given return value type. 193 | * @param context Context. 194 | * @param iTypeId Type id of the return value. 195 | * @param uiFlags Type flags. 196 | * @param pReturnValue pointer to the variable that will receive the return value. 197 | * @return true on success, false otherwise. 198 | */ 199 | bool GetReturnValue( asIScriptContext& context, int iTypeId, asDWORD uiFlags, void* pReturnValue ); 200 | } 201 | 202 | /** @} */ 203 | 204 | #endif //UTIL_CONTEXTUTILS_H -------------------------------------------------------------------------------- /src/AngelscriptUtils/util/IASExtendAdapter.h: -------------------------------------------------------------------------------- 1 | #ifndef ANGELSCRIPT_UTIL_IASEXTENDADAPTER_H 2 | #define ANGELSCRIPT_UTIL_IASEXTENDADAPTER_H 3 | 4 | #include "CASObjPtr.h" 5 | 6 | /** 7 | * @addtogroup ASExtend 8 | * 9 | * @{ 10 | */ 11 | 12 | /** 13 | * Interface used to adapt C++ classes for extension in Angelscript. 14 | */ 15 | class IASExtendAdapter 16 | { 17 | public: 18 | virtual ~IASExtendAdapter() = 0; 19 | 20 | /** 21 | * @return The object pointer. 22 | */ 23 | virtual const CASObjPtr& GetObject() const = 0; 24 | 25 | /** 26 | * @copydoc GetObject() const 27 | */ 28 | virtual CASObjPtr GetObject() = 0; 29 | }; 30 | 31 | inline IASExtendAdapter::~IASExtendAdapter() 32 | { 33 | } 34 | 35 | /** @} */ 36 | 37 | #endif //ANGELSCRIPT_UTIL_IASEXTENDADAPTER_H -------------------------------------------------------------------------------- /src/AngelscriptUtils/util/StringUtils.h: -------------------------------------------------------------------------------- 1 | #ifndef ANGELSCRIPT_UTIL_STRINGUTILS_H 2 | #define ANGELSCRIPT_UTIL_STRINGUTILS_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | //Implemented in the as namespace to prevent collisions with other implementations. 11 | namespace as 12 | { 13 | /** 14 | * Taken from MSVC string hash. 15 | */ 16 | inline size_t StringHash( const char* const pszString ) 17 | { 18 | #if defined( _WIN64 ) || ( defined( __GNUC__ ) && ( __x86_64__ || __ppc64__ ) ) 19 | static_assert( sizeof( size_t ) == 8, "This code is for 64-bit size_t." ); 20 | const size_t _FNV_offset_basis = 14695981039346656037ULL; 21 | const size_t _FNV_prime = 1099511628211ULL; 22 | 23 | #else /* defined(_WIN64) */ 24 | static_assert( sizeof( size_t ) == 4, "This code is for 32-bit size_t." ); 25 | const size_t _FNV_offset_basis = 2166136261U; 26 | const size_t _FNV_prime = 16777619U; 27 | #endif /* defined(_WIN64) */ 28 | 29 | const size_t _Count = strlen( pszString ); 30 | 31 | size_t _Val = _FNV_offset_basis; 32 | for( size_t _Next = 0; _Next < _Count; ++_Next ) 33 | { // fold in another byte 34 | _Val ^= ( size_t ) pszString[ _Next ]; 35 | _Val *= _FNV_prime; 36 | } 37 | return ( _Val ); 38 | } 39 | 40 | template 41 | struct Hash_C_String final : public std::unary_function 42 | { 43 | std::size_t operator()( STR pszStr ) const 44 | { 45 | return StringHash( pszStr ); 46 | } 47 | }; 48 | 49 | template 50 | struct EqualTo_C_String final 51 | { 52 | bool operator()( STR lhs, STR rhs ) const 53 | { 54 | return COMPARE( lhs, rhs ) == 0; 55 | } 56 | }; 57 | 58 | /* 59 | * This code is based on the following Stack Overflow answer: http://stackoverflow.com/a/217605 60 | */ 61 | // trim from start 62 | inline std::string& LTrim( std::string& s ) 63 | { 64 | s.erase( s.begin(), std::find_if( s.begin(), s.end(), 65 | std::not1( std::ptr_fun( std::isspace ) ) ) ); 66 | return s; 67 | } 68 | 69 | // trim from end 70 | inline std::string& RTrim( std::string& s ) 71 | { 72 | s.erase( std::find_if( s.rbegin(), s.rend(), 73 | std::not1( std::ptr_fun( std::isspace ) ) ).base(), s.end() ); 74 | return s; 75 | } 76 | 77 | // trim from both ends 78 | inline std::string& Trim( std::string& s ) 79 | { 80 | return LTrim( RTrim( s ) ); 81 | } 82 | 83 | /* 84 | * End based on code. 85 | */ 86 | 87 | /** 88 | * Checks if a printf operation was successful 89 | */ 90 | inline bool PrintfSuccess( const int iRet, const size_t uiBufferSize ) 91 | { 92 | return iRet >= 0 && static_cast( iRet ) < uiBufferSize; 93 | } 94 | } 95 | 96 | #endif //ANGELSCRIPT_UTIL_STRINGUTILS_H -------------------------------------------------------------------------------- /src/AngelscriptUtils/wrapper/ASCallableConst.h: -------------------------------------------------------------------------------- 1 | #ifndef ANGELSCRIPT_WRAPPER_ASCALLABLECONST_H 2 | #define ANGELSCRIPT_WRAPPER_ASCALLABLECONST_H 3 | 4 | #include 5 | 6 | /** 7 | * @addtogroup ASCallable 8 | * 9 | * @{ 10 | */ 11 | 12 | typedef uint32_t CallFlags_t; 13 | 14 | namespace CallFlag 15 | { 16 | /** 17 | * Flags to affect function calls. 18 | */ 19 | enum CallFlag : CallFlags_t 20 | { 21 | /** 22 | * No flags. 23 | */ 24 | NONE = 0, 25 | }; 26 | } 27 | 28 | /** @} */ 29 | 30 | #endif //ANGELSCRIPT_WRAPPER_ASCALLABLECONST_H 31 | -------------------------------------------------------------------------------- /src/AngelscriptUtils/wrapper/CASArguments.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | #include "AngelscriptUtils/CASManager.h" 7 | #include "AngelscriptUtils/util/ASLogging.h" 8 | #include "AngelscriptUtils/util/ASUtil.h" 9 | #include "AngelscriptUtils/util/ContextUtils.h" 10 | 11 | #include "CASArguments.h" 12 | 13 | CASArgument::~CASArgument() 14 | { 15 | Reset(); 16 | } 17 | 18 | CASArgument::CASArgument( const CASArgument& other ) 19 | { 20 | Set( other ); 21 | } 22 | 23 | CASArgument& CASArgument::operator=( const CASArgument& other ) 24 | { 25 | Set( other ); 26 | 27 | return *this; 28 | } 29 | 30 | void* CASArgument::GetArgumentAsPointer() const 31 | { 32 | if( !HasValue() ) 33 | return nullptr; 34 | 35 | switch( m_ArgType ) 36 | { 37 | case ArgType::PRIMITIVE: 38 | case ArgType::ENUM: return const_cast( &m_Value.qword ); 39 | 40 | case ArgType::REF: 41 | case ArgType::VALUE: return m_Value.pValue; 42 | 43 | default: return nullptr; 44 | } 45 | } 46 | 47 | bool CASArgument::Set( asIScriptEngine& engine, const int iTypeId, const ArgType::ArgType type, const ArgumentValue& value, const bool bCopy ) 48 | { 49 | Reset(); 50 | 51 | if( type == ArgType::NONE ) 52 | return true; 53 | 54 | bool bSuccess = true; 55 | 56 | m_iTypeId = iTypeId; 57 | m_ArgType = type; 58 | 59 | if( bCopy ) 60 | { 61 | if( type == ArgType::VALUE || type == ArgType::REF ) 62 | { 63 | if( asITypeInfo* pType = engine.GetTypeInfoById( iTypeId ) ) 64 | { 65 | //Need to copy value 66 | if( type == ArgType::VALUE ) 67 | { 68 | m_Value.pValue = engine.CreateScriptObjectCopy( value.pValue, pType ); 69 | } 70 | else 71 | { 72 | //Need to addref 73 | engine.AddRefScriptObject( value.pValue, pType ); 74 | m_Value = value; 75 | } 76 | } 77 | else 78 | { 79 | as::log->critical( "CASArgument::Set: Failed to get object type!" ); 80 | bSuccess = false; 81 | } 82 | } 83 | else if( type == ArgType::VOID ) 84 | { 85 | //Do nothing 86 | } 87 | else 88 | { 89 | //Primitive type or enum, just copy 90 | m_Value = value; 91 | } 92 | } 93 | else if( type != ArgType::VOID ) 94 | { 95 | m_Value = value; 96 | } 97 | 98 | return bSuccess; 99 | } 100 | 101 | bool CASArgument::Set( const int iTypeId, const ArgType::ArgType type, const ArgumentValue& value, const bool bCopy ) 102 | { 103 | return Set( *CASManager::GetActiveManager()->GetEngine(), iTypeId, type, value, bCopy ); 104 | } 105 | 106 | bool CASArgument::Set( const CASArgument& other ) 107 | { 108 | if( this == &other ) 109 | return true; 110 | 111 | return Set( other.GetTypeId(), other.GetArgumentType(), other.GetArgumentValue(), true ); 112 | } 113 | 114 | void CASArgument::Reset() 115 | { 116 | if( HasValue() ) 117 | { 118 | //Release reference if needed 119 | if( !as::IsPrimitive( m_iTypeId ) && !as::IsEnum( m_iTypeId ) ) 120 | { 121 | auto pEngine = CASManager::GetActiveManager()->GetEngine(); 122 | 123 | asITypeInfo* pType = pEngine->GetTypeInfoById( m_iTypeId ); 124 | 125 | if( pType ) 126 | pEngine->ReleaseScriptObject( m_Value.pValue, pType ); 127 | else 128 | { 129 | as::log->critical( "CASArgument::Reset: Failed to get object type!" ); 130 | } 131 | } 132 | 133 | m_iTypeId = -1; 134 | m_ArgType = ArgType::NONE; 135 | m_Value = ArgumentValue(); 136 | } 137 | } 138 | 139 | CASArguments::CASArguments( asIScriptGeneric& arguments, size_t uiStartIndex ) 140 | { 141 | SetArguments( arguments, uiStartIndex ); 142 | } 143 | 144 | CASArguments::CASArguments( asIScriptFunction& targetFunc, va_list list ) 145 | { 146 | SetArguments( targetFunc, list ); 147 | } 148 | 149 | CASArguments::~CASArguments() 150 | { 151 | Clear(); 152 | } 153 | 154 | void CASArguments::Release() const 155 | { 156 | if( InternalRelease() ) 157 | delete this; 158 | } 159 | 160 | CASArguments::CASArguments( const CASArguments& other ) 161 | { 162 | Assign( other ); 163 | } 164 | 165 | CASArguments& CASArguments::operator=( const CASArguments& other ) 166 | { 167 | Assign( other ); 168 | 169 | return *this; 170 | } 171 | 172 | void CASArguments::Assign( const CASArguments& other ) 173 | { 174 | if( this != &other ) 175 | { 176 | Clear(); 177 | 178 | m_Arguments.resize( other.GetArgumentCount() ); 179 | 180 | if( other.HasArguments() ) 181 | { 182 | const auto& sourceArgs = other.GetArgumentList(); 183 | 184 | //Failure is unlikely, but there might be issues copying between lists that don't occur in init from scripts 185 | bool bSuccess = true; 186 | 187 | auto pEngine = CASManager::GetActiveManager()->GetEngine(); 188 | 189 | for( size_t uiIndex = 0; uiIndex < m_Arguments.size() && bSuccess; ++uiIndex ) 190 | { 191 | const CASArgument& sourceArg = sourceArgs[ uiIndex ]; 192 | 193 | bSuccess = m_Arguments[ uiIndex ].Set( *pEngine, sourceArg.GetTypeId(), sourceArg.GetArgumentType(), sourceArg.GetArgumentValue(), true ); 194 | } 195 | 196 | if( !bSuccess ) 197 | Clear(); 198 | } 199 | } 200 | } 201 | 202 | void CASArguments::Clear() 203 | { 204 | m_Arguments.clear(); 205 | m_Arguments.shrink_to_fit(); 206 | } 207 | 208 | const CASArgument* CASArguments::GetArgument( const size_t uiIndex ) const 209 | { 210 | assert( uiIndex < m_Arguments.size() ); 211 | 212 | if( uiIndex >= m_Arguments.size() ) 213 | return nullptr; 214 | 215 | return &m_Arguments[ uiIndex ]; 216 | } 217 | 218 | bool CASArguments::SetArguments( asIScriptGeneric& arguments, size_t uiStartIndex ) 219 | { 220 | const size_t uiArgCount = static_cast( arguments.GetArgCount() ); 221 | 222 | //If true, an internal error occured 223 | if( uiStartIndex > uiArgCount ) 224 | { 225 | as::log->critical( "CASArguments::SetArguments: Start index is greater than argument count!" ); 226 | return false; 227 | } 228 | 229 | const asUINT uiTargetArgs = uiArgCount - uiStartIndex; 230 | 231 | bool bSuccess = true; 232 | 233 | Arguments_t args( uiTargetArgs ); 234 | 235 | auto pEngine = CASManager::GetActiveManager()->GetEngine(); 236 | 237 | for( asUINT uiIndex = 0; uiIndex < uiTargetArgs && bSuccess; ++uiIndex ) 238 | { 239 | void* pData = arguments.GetArgAddress( uiIndex + uiStartIndex ); 240 | int iTypeId = arguments.GetArgTypeId( uiIndex + uiStartIndex ); 241 | 242 | bSuccess = ctx::SetArgument( *pEngine, pData, iTypeId, args[ uiIndex ] ); 243 | } 244 | 245 | if( bSuccess ) 246 | { 247 | m_Arguments = std::move( args ); 248 | } 249 | 250 | return bSuccess; 251 | } 252 | 253 | //Store arguments in this object 254 | bool CASArguments::SetArguments( asIScriptFunction& targetFunc, va_list list ) 255 | { 256 | if( !list ) 257 | return false; 258 | 259 | Clear(); 260 | 261 | const asUINT uiArgCount = targetFunc.GetParamCount(); 262 | 263 | Arguments_t args( uiArgCount ); 264 | 265 | bool bSuccess = true; 266 | 267 | auto pEngine = CASManager::GetActiveManager()->GetEngine(); 268 | 269 | int iTypeId; 270 | asDWORD uiFlags; 271 | 272 | ArgumentValue value; 273 | 274 | ctx::VAList vaList; 275 | 276 | //GCC fails to copy the list if it's done any other way. 277 | va_copy( vaList.list, list ); 278 | 279 | for( asUINT uiIndex = 0; uiIndex < uiArgCount && bSuccess; ++uiIndex ) 280 | { 281 | if( targetFunc.GetParam( uiIndex, &iTypeId, &uiFlags ) < 0 ) 282 | { 283 | as::log->critical( "CASArguments::SetArguments(va_list): An error occurred while getting function parameter information, aborting!" ); 284 | bSuccess = false; 285 | break; 286 | } 287 | 288 | asITypeInfo* pType = pEngine->GetTypeInfoById( iTypeId ); 289 | 290 | asDWORD uiObjFlags = pType->GetFlags(); 291 | ArgType::ArgType argType; 292 | 293 | if( ( bSuccess = ctx::GetArgumentFromVarargs( value, iTypeId, uiFlags, vaList, &uiObjFlags, &argType ) ) != false ) 294 | { 295 | //Make copies of the input arguments; they won't exist anymore once this method has finished execution. 296 | args[ uiIndex ].Set( *pEngine, iTypeId, argType, value, true ); 297 | } 298 | else 299 | { 300 | const auto szFunctionName = as::FormatFunctionName( targetFunc ); 301 | 302 | as::log->critical( "CASArguments::SetArguments(va_list): Function '{}': failed to set argument {}, aborting!", 303 | szFunctionName, uiIndex ); 304 | } 305 | } 306 | 307 | if( bSuccess ) 308 | { 309 | m_Arguments = std::move( args ); 310 | } 311 | 312 | return bSuccess; 313 | } -------------------------------------------------------------------------------- /src/AngelscriptUtils/wrapper/CASArguments.h: -------------------------------------------------------------------------------- 1 | #ifndef ANGELSCRIPT_CASARGUMENTS_H 2 | #define ANGELSCRIPT_CASARGUMENTS_H 3 | 4 | #include 5 | 6 | #include "AngelscriptUtils/util/CASBaseClass.h" 7 | 8 | class asIScriptEngine; 9 | 10 | /** 11 | * @defgroup ASArguments Angelscript Arguments Utils 12 | * Everything related to handling arguments is in here. 13 | * 14 | * @{ 15 | */ 16 | 17 | namespace ArgType 18 | { 19 | /** 20 | * Possible types that an argument can be. 21 | * TODO: shouldn't be a bit field. 22 | * TODO: shouldn't this be trivial to determine using helper functions? 23 | * TODO: move to ASUtil.h 24 | * TODO: probably obsolete due to ITypeInfo's existence 25 | */ 26 | enum ArgType 27 | { 28 | /** 29 | * No type set. 30 | */ 31 | NONE = 1 << 0, 32 | 33 | /** 34 | * No return type. 35 | */ 36 | VOID = 1 << 1, 37 | PRIMITIVE = 1 << 2, 38 | VALUE = 1 << 3, 39 | REF = 1 << 4, 40 | 41 | /** 42 | * It's an enum, treat as dword. 43 | */ 44 | ENUM = 1 << 5, 45 | }; 46 | } 47 | 48 | /** 49 | * Can store the value of an argument. 50 | */ 51 | struct ArgumentValue final 52 | { 53 | union 54 | { 55 | asBYTE byte; 56 | asWORD word; 57 | asDWORD dword; 58 | asQWORD qword; 59 | 60 | float flValue; 61 | double dValue; 62 | 63 | void* pValue; 64 | }; 65 | 66 | ArgumentValue() 67 | : qword() 68 | { 69 | } 70 | 71 | }; 72 | 73 | /** 74 | * Represents a single argument. 75 | */ 76 | class CASArgument final 77 | { 78 | public: 79 | 80 | /** 81 | * Default constructor. 82 | */ 83 | CASArgument() = default; 84 | 85 | /** 86 | * Destructor. 87 | */ 88 | ~CASArgument(); 89 | 90 | /** 91 | * Copy constructor. 92 | */ 93 | CASArgument( const CASArgument& other ); 94 | 95 | /** 96 | * Assignment operator. 97 | */ 98 | CASArgument& operator=( const CASArgument& other ); 99 | 100 | /** 101 | * @return The type id. 102 | */ 103 | inline int GetTypeId() const { return m_iTypeId; } 104 | 105 | /** 106 | * @return The argument type. 107 | */ 108 | inline ArgType::ArgType GetArgumentType() const { return m_ArgType; } 109 | 110 | /** 111 | * @return The argument value. 112 | */ 113 | inline const ArgumentValue& GetArgumentValue() const { return m_Value; } 114 | 115 | /** 116 | * @copydoc GetArgumentValue() const 117 | */ 118 | inline ArgumentValue& GetArgumentValue() { return m_Value; } 119 | 120 | /** 121 | * @return Whether this argument has a value. 122 | */ 123 | bool HasValue() const { return !( m_ArgType & ( ArgType::VOID | ArgType::NONE ) ); } 124 | 125 | /** 126 | * Gets the address of the argument. 127 | * For read access only! 128 | * @return The address of the argument. 129 | */ 130 | void* GetArgumentAsPointer() const; 131 | 132 | /** 133 | * Sets the argument to the given value and type. 134 | * @param engine Engine to use. 135 | * @param iTypeId Type Id. 136 | * @param type Argument type. 137 | * @param value Value to assign. 138 | * @param bCopy Whether to copy the value, or point to the same instance. 139 | * @return true on success, false otherwise. 140 | */ 141 | bool Set( asIScriptEngine& engine, const int iTypeId, const ArgType::ArgType type, const ArgumentValue& value, const bool bCopy = false ); 142 | 143 | /** 144 | * Same as the other version, but will retrieve the engine from the active manager instead. 145 | * @see Set( asIScriptEngine& engine, const int iTypeId, const ArgType::ArgType type, const ArgumentValue& value, const bool bCopy = false ) 146 | */ 147 | bool Set( const int iTypeId, const ArgType::ArgType type, const ArgumentValue& value, const bool bCopy = false ); 148 | 149 | /** 150 | * Sets the argument to that of the given argument. The value is copy constructed, or in the case of ref types, a reference is added. 151 | * @param other Argument to copy. 152 | * @return true on success, false otherwise. 153 | */ 154 | bool Set( const CASArgument& other ); 155 | 156 | /** 157 | * Resets the argument. It is left with no value. 158 | */ 159 | void Reset(); 160 | 161 | private: 162 | 163 | //Object type id 164 | int m_iTypeId = -1; 165 | 166 | //Used to prevent looking up the type again if it involves expensive lookup 167 | ArgType::ArgType m_ArgType = ArgType::NONE; 168 | 169 | //The actual value. 170 | ArgumentValue m_Value = ArgumentValue(); 171 | }; 172 | 173 | /** 174 | * This class can store a variable number of arguments. 175 | */ 176 | class CASArguments final : public CASRefCountedBaseClass 177 | { 178 | public: 179 | typedef std::vector Arguments_t; 180 | 181 | public: 182 | 183 | /** 184 | * Default constructor. Creates an empty argument list. 185 | */ 186 | CASArguments() = default; 187 | 188 | /** 189 | * Constructor. Creates a list of arguments based on the given generic call instance. 190 | * @param arguments Generic call instance. 191 | * @param uiStartIndex The index of the first argument to use. 192 | * @see SetArguments( asIScriptGeneric& arguments, size_t uiStartIndex ) 193 | */ 194 | CASArguments( asIScriptGeneric& arguments, size_t uiStartIndex = 0 ); 195 | 196 | /** 197 | * Constructor. Creates a list of arguments based on the given function, and the given varargs pointer. 198 | * @param targetFunc Function whose arguments will be used for type info. 199 | * @param list Pointer to the arguments to use. 200 | * @see SetArguments( asIScriptFunction& targetFunc, va_list list ) 201 | */ 202 | CASArguments( asIScriptFunction& targetFunc, va_list list ); 203 | 204 | /** 205 | * Destructor. 206 | */ 207 | ~CASArguments(); 208 | 209 | void Release() const; 210 | 211 | /** 212 | * Copy constructor. 213 | */ 214 | CASArguments( const CASArguments& other ); 215 | 216 | /** 217 | * Assignment operator. 218 | */ 219 | CASArguments& operator=( const CASArguments& other ); 220 | 221 | /** 222 | * Copies the arguments from the given arguments object to this one. 223 | */ 224 | void Assign( const CASArguments& other ); 225 | 226 | /** 227 | * Clears the list of arguments. 228 | */ 229 | void Clear(); 230 | 231 | /** 232 | * @return The list of arguments. 233 | */ 234 | const Arguments_t& GetArgumentList() const { return m_Arguments; } 235 | 236 | /** 237 | * @return The number of arguments. 238 | */ 239 | size_t GetArgumentCount() const { return m_Arguments.size(); } 240 | 241 | /** 242 | * Gets the argument at the given index. 243 | * @return The requested argument, or null if the index is invalid. 244 | */ 245 | const CASArgument* GetArgument( const size_t uiIndex ) const; 246 | 247 | /** 248 | * @return Whether there are any arguments in this object. 249 | */ 250 | bool HasArguments() const { return !m_Arguments.empty(); } 251 | 252 | /** 253 | * Sets the list of arguments to that of the given generic call instance. 254 | * @param arguments Generic call instance. 255 | * @param uiStartIndex The index of the first argument to use. 256 | * @return true on success, false otherwise. 257 | */ 258 | bool SetArguments( asIScriptGeneric& arguments, size_t uiStartIndex = 0 ); 259 | 260 | /** 261 | * Sets the list of arguments to that of the given function, and the given varargs pointer. 262 | * @param targetFunc Function whose arguments will be used for type info. 263 | * @param list Pointer to the arguments to use. 264 | * @return true on success, false otherwise. 265 | */ 266 | bool SetArguments( asIScriptFunction& targetFunc, va_list list ); 267 | 268 | private: 269 | Arguments_t m_Arguments; 270 | }; 271 | 272 | /** @} */ 273 | 274 | #endif //ANGELSCRIPT_CASARGUMENTS_H 275 | -------------------------------------------------------------------------------- /src/AngelscriptUtils/wrapper/CASContext.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "AngelscriptUtils/IASContextResultHandler.h" 4 | 5 | #include "CASContext.h" 6 | 7 | void CASOwningContext::Release() 8 | { 9 | if( m_pContext ) 10 | { 11 | const auto result = m_pContext->Unprepare(); 12 | 13 | auto pResultHandler = as::GetContextResultHandler( *m_pContext ); 14 | 15 | if( pResultHandler ) 16 | pResultHandler->ProcessUnprepareResult( *m_pContext, result ); 17 | } 18 | 19 | if( m_pEngine ) 20 | { 21 | m_pEngine->ReturnContext( m_pContext ); 22 | m_pContext = nullptr; 23 | 24 | m_pEngine->Release(); 25 | m_pEngine = nullptr; 26 | } 27 | else if( m_pContext ) 28 | { 29 | m_pContext->Release(); 30 | m_pContext = nullptr; 31 | } 32 | } 33 | 34 | void CASOwningContext::ReleaseOwnership() 35 | { 36 | if( m_pContext ) 37 | { 38 | m_pContext = nullptr; 39 | } 40 | 41 | if( m_pEngine ) 42 | { 43 | m_pEngine = nullptr; 44 | } 45 | } -------------------------------------------------------------------------------- /src/AngelscriptUtils/wrapper/CASContext.h: -------------------------------------------------------------------------------- 1 | #ifndef WRAPPER_CASCONTEXT_H 2 | #define WRAPPER_CASCONTEXT_H 3 | 4 | #include 5 | 6 | /** 7 | * @defgroup ASContext Angelscript Context Utils 8 | * 9 | * @{ 10 | */ 11 | 12 | /** 13 | * A context that does not release the context in its destructor. 14 | */ 15 | class CASContext 16 | { 17 | public: 18 | /** 19 | * Constructor. The context is not AddRef'd. 20 | * @param context Context. 21 | */ 22 | CASContext( asIScriptContext& context ) 23 | : m_pContext( &context ) 24 | { 25 | } 26 | 27 | ~CASContext() = default; 28 | 29 | public: 30 | 31 | /** 32 | * @return Whether this context is valid. 33 | */ 34 | operator bool() const { return m_pContext != nullptr; } 35 | 36 | asIScriptContext* GetContext() { return m_pContext; } 37 | 38 | protected: 39 | asIScriptContext* m_pContext = nullptr; 40 | 41 | private: 42 | CASContext( const CASContext& ) = delete; 43 | CASContext& operator=( const CASContext& ) = delete; 44 | }; 45 | 46 | /** 47 | * RAII wrapper around a context that maintains ownership for its lifetime. 48 | */ 49 | class CASOwningContext final : public CASContext 50 | { 51 | public: 52 | /** 53 | * Constructor. The context is AddRef'd. 54 | * @param context Context. 55 | */ 56 | CASOwningContext( asIScriptContext& context ) 57 | : CASContext( context ) 58 | { 59 | m_pContext->AddRef(); 60 | } 61 | 62 | /** 63 | * Constructor. A context is acquired using asIScriptEngine::RequestContext. 64 | * @param engine Script engine. 65 | */ 66 | CASOwningContext( asIScriptEngine& engine ) 67 | : CASContext( *engine.RequestContext() ) 68 | { 69 | m_pEngine = &engine; 70 | 71 | m_pEngine->AddRef(); 72 | } 73 | 74 | /** 75 | * Destructor. 76 | */ 77 | ~CASOwningContext() 78 | { 79 | Release(); 80 | } 81 | 82 | /** 83 | * Releases the context. 84 | */ 85 | void Release(); 86 | 87 | /** 88 | * Releases ownership of the context. 89 | */ 90 | void ReleaseOwnership(); 91 | 92 | private: 93 | //TODO: consider: the engine can be retrieved using m_pContext->GetEngine. All that's needed is a flag that indicates where it came from. 94 | asIScriptEngine* m_pEngine = nullptr; 95 | }; 96 | 97 | /** @} */ 98 | 99 | #endif //WRAPPER_CASCONTEXT_H -------------------------------------------------------------------------------- /src/AngelscriptUtils/wrapper/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_sources( 2 | ASCallableConst.h 3 | ASCallable.h 4 | CASArguments.h 5 | CASArguments.cpp 6 | CASContext.h 7 | CASContext.cpp 8 | ) 9 | 10 | add_includes( 11 | ASCallable.h 12 | ASCallableConst.h 13 | CASArguments.h 14 | CASContext.h 15 | ) 16 | -------------------------------------------------------------------------------- /src/AngelscriptUtilsTest/ASCBaseEntity.h: -------------------------------------------------------------------------------- 1 | #ifndef TEST_ASCBASEENTITY_H 2 | #define TEST_ASCBASEENTITY_H 3 | 4 | #include 5 | 6 | #include "CBaseEntity.h" 7 | 8 | /** 9 | * Class name for CBaseEntity in scripts. 10 | */ 11 | #define AS_CBASEENTITY_CLASSNAME "CBaseEntity" 12 | 13 | /** 14 | * Registers CBaseEntity for use in scripts. 15 | * @param engine Script engine. 16 | */ 17 | inline void RegisterScriptCBaseEntity( asIScriptEngine& engine ) 18 | { 19 | const char* const pszObjectName = AS_CBASEENTITY_CLASSNAME; 20 | 21 | engine.RegisterObjectType( pszObjectName, 0, asOBJ_REF | asOBJ_NOCOUNT ); 22 | 23 | engine.RegisterObjectMethod( pszObjectName, "void Spawn()", asMETHOD( CBaseEntity, Spawn ), asCALL_THISCALL ); 24 | } 25 | 26 | /** 27 | * These functions are used to call base class versions of methods. 28 | */ 29 | 30 | template 31 | void BaseEntity_Spawn( BASECLASS* pThis ) 32 | { 33 | pThis->BASECLASS::Spawn(); 34 | } 35 | 36 | template 37 | int BaseEntity_ScheduleOfType( BASECLASS* pThis, const std::string& szName ) 38 | { 39 | return pThis->BASECLASS::ScheduleOfType( szName ); 40 | } 41 | 42 | /** 43 | * Registers the base version of an entity's CBaseEntity methods. This allow scripts to call base class implementations. 44 | * @param engine Script engine. 45 | * @param pszObjectName Class name. 46 | * @tparam BASECLASS Entity class type. 47 | */ 48 | template 49 | void RegisterScriptBaseEntity( asIScriptEngine& engine, const char* const pszObjectName ) 50 | { 51 | engine.RegisterObjectType( pszObjectName, 0, asOBJ_REF | asOBJ_NOCOUNT ); 52 | 53 | engine.RegisterObjectMethod( pszObjectName, "void Spawn()", asFUNCTION( BaseEntity_Spawn ), asCALL_CDECL_OBJFIRST ); 54 | 55 | engine.RegisterObjectMethod( pszObjectName, "int ScheduleOfType(const string& in szName)", asFUNCTION( BaseEntity_ScheduleOfType ), asCALL_CDECL_OBJFIRST ); 56 | } 57 | 58 | /** 59 | * Registers the base version of CBaseEntity. 60 | * @param engine Script engine. 61 | */ 62 | inline void RegisterScriptBaseEntity( asIScriptEngine& engine ) 63 | { 64 | //The base name is just the regular name without the 'C'. 65 | RegisterScriptBaseEntity( engine, AS_CBASEENTITY_CLASSNAME + 1 ); 66 | } 67 | 68 | #endif //TEST_ASCBASEENTITY_H -------------------------------------------------------------------------------- /src/AngelscriptUtilsTest/CBaseEntity.cpp: -------------------------------------------------------------------------------- 1 | #include "CBaseEntity.h" -------------------------------------------------------------------------------- /src/AngelscriptUtilsTest/CBaseEntity.h: -------------------------------------------------------------------------------- 1 | #ifndef TEST_CBASEENTITY_H 2 | #define TEST_CBASEENTITY_H 3 | 4 | #include 5 | 6 | #include "AngelscriptUtils/util/ASPlatform.h" 7 | 8 | class CBaseEntity 9 | { 10 | public: 11 | 12 | virtual void Spawn() 13 | { 14 | } 15 | 16 | virtual int ScheduleOfType( const std::string& /*szName*/ ) 17 | { 18 | return 1; 19 | } 20 | }; 21 | 22 | #endif //TEST_CBASEENTITY_H -------------------------------------------------------------------------------- /src/AngelscriptUtilsTest/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # AngelscriptUtils Test project 3 | # 4 | 5 | set( TARGET_NAME AngelscriptUtilsTest ) 6 | 7 | add_sources( 8 | ASCBaseEntity.h 9 | CBaseEntity.cpp 10 | CBaseEntity.h 11 | CScriptBaseEntity.h 12 | Main.cpp 13 | add_on/scriptany/scriptany.cpp 14 | add_on/scriptany/scriptany.h 15 | add_on/scriptarray/scriptarray.cpp 16 | add_on/scriptarray/scriptarray.h 17 | add_on/scriptdictionary/scriptdictionary.cpp 18 | add_on/scriptdictionary/scriptdictionary.h 19 | add_on/scriptstdstring/scriptstdstring.cpp 20 | add_on/scriptstdstring/scriptstdstring_utils.cpp 21 | add_on/scriptstdstring/scriptstdstring.h 22 | ) 23 | 24 | preprocess_sources() 25 | 26 | add_executable( ${TARGET_NAME} ${PREP_SRCS} ) 27 | 28 | check_winxp_support( ${TARGET_NAME} ) 29 | 30 | configure_msvc_runtime( ${TARGET_NAME} ${MSVC_RUNTIME_CONFIG} ) 31 | 32 | target_include_directories( ${TARGET_NAME} PRIVATE 33 | ${CMAKE_CURRENT_SOURCE_DIR} 34 | ${SRC_DIR} 35 | ) 36 | 37 | target_compile_definitions( ${TARGET_NAME} PRIVATE 38 | ${SHARED_DEFS} 39 | ) 40 | 41 | set_target_properties( ${TARGET_NAME} PROPERTIES 42 | COMPILE_FLAGS "${SHARED_COMPILE_FLAGS}" 43 | LINK_FLAGS "${SHARED_LINK_FLAGS}" 44 | ) 45 | 46 | #Create filters 47 | create_source_groups( "${SRC_DIR}" ) 48 | 49 | # Indicate which libraries to include during the link process. 50 | target_link_libraries( ${TARGET_NAME} 51 | AngelscriptUtils 52 | ) 53 | 54 | #CMake places libraries in /Debug or /Release on Windows, so explicitly set the paths for both. 55 | #On Linux, it uses LIBRARY_OUTPUT_DIRECTORY 56 | set_target_properties( ${TARGET_NAME} PROPERTIES 57 | RUNTIME_OUTPUT_DIRECTORY "${OUTPUT_DIR}" 58 | RUNTIME_OUTPUT_DIRECTORY_DEBUG "${OUTPUT_DIR}" 59 | RUNTIME_OUTPUT_DIRECTORY_RELEASE "${OUTPUT_DIR}" 60 | RUNTIME_OUTPUT_MINSIZEREL "${OUTPUT_DIR}" 61 | RUNTIME_OUTPUT_RELWITHDEBINFO "${OUTPUT_DIR}" 62 | ) 63 | 64 | install( TARGETS ${TARGET_NAME} DESTINATION bin ) 65 | install_includes( "${SRC_DIR}" ) 66 | 67 | clear_sources() 68 | -------------------------------------------------------------------------------- /src/AngelscriptUtilsTest/CScriptBaseEntity.h: -------------------------------------------------------------------------------- 1 | #ifndef TEST_CSCRIPTBASEENTITY_H 2 | #define TEST_CSCRIPTBASEENTITY_H 3 | 4 | #include "AngelscriptUtils/util/CASExtendAdapter.h" 5 | #include "CBaseEntity.h" 6 | 7 | /** 8 | * Class that bridges the gap between C++ and Angelscript method calls. 9 | */ 10 | class CScriptBaseEntity : public CASExtendAdapter 11 | { 12 | public: 13 | typedef CASExtendAdapter BaseClass; 14 | typedef CScriptBaseEntity ThisClass; 15 | 16 | public: 17 | CScriptBaseEntity( CASObjPtr object ) 18 | : CASExtendAdapter( object ) 19 | { 20 | } 21 | 22 | void Spawn() override 23 | { 24 | CALL_EXTEND_FUNC( Spawn, "()" ); 25 | } 26 | 27 | //This is used to handle the reference type being a pointer. 28 | int ScheduleOfTypePtr( const std::string* pszName ) 29 | { 30 | return BaseClass::ScheduleOfType( *pszName ); 31 | } 32 | 33 | int ScheduleOfType( const std::string& szName ) override 34 | { 35 | CALL_EXTEND_FUNC_RET_DIFFFUNC( int, ScheduleOfType, ThisClass::ScheduleOfTypePtr, "(const string& in)", &szName ); 36 | } 37 | }; 38 | 39 | #endif //TEST_CSCRIPTBASEENTITY_H -------------------------------------------------------------------------------- /src/AngelscriptUtilsTest/add_on/scriptany/scriptany.h: -------------------------------------------------------------------------------- 1 | #ifndef SCRIPTANY_H 2 | #define SCRIPTANY_H 3 | 4 | #ifndef ANGELSCRIPT_H 5 | // Avoid having to inform include path if header is already include before 6 | #include 7 | #endif 8 | 9 | 10 | BEGIN_AS_NAMESPACE 11 | 12 | class CScriptAny 13 | { 14 | public: 15 | // Constructors 16 | CScriptAny(asIScriptEngine *engine); 17 | CScriptAny(void *ref, int refTypeId, asIScriptEngine *engine); 18 | 19 | // Memory management 20 | int AddRef() const; 21 | int Release() const; 22 | 23 | // Copy the stored value from another any object 24 | CScriptAny &operator=(const CScriptAny&); 25 | int CopyFrom(const CScriptAny *other); 26 | 27 | // Store the value, either as variable type, integer number, or real number 28 | void Store(void *ref, int refTypeId); 29 | void Store(asINT64 &value); 30 | void Store(double &value); 31 | 32 | // Retrieve the stored value, either as variable type, integer number, or real number 33 | bool Retrieve(void *ref, int refTypeId) const; 34 | bool Retrieve(asINT64 &value) const; 35 | bool Retrieve(double &value) const; 36 | 37 | // Get the type id of the stored value 38 | int GetTypeId() const; 39 | 40 | // GC methods 41 | int GetRefCount(); 42 | void SetFlag(); 43 | bool GetFlag(); 44 | void EnumReferences(asIScriptEngine *engine); 45 | void ReleaseAllHandles(asIScriptEngine *engine); 46 | 47 | protected: 48 | virtual ~CScriptAny(); 49 | void FreeObject(); 50 | 51 | mutable int refCount; 52 | mutable bool gcFlag; 53 | asIScriptEngine *engine; 54 | 55 | // The structure for holding the values 56 | struct valueStruct 57 | { 58 | union 59 | { 60 | asINT64 valueInt; 61 | double valueFlt; 62 | void *valueObj; 63 | }; 64 | int typeId; 65 | }; 66 | 67 | valueStruct value; 68 | }; 69 | 70 | void RegisterScriptAny(asIScriptEngine *engine); 71 | void RegisterScriptAny_Native(asIScriptEngine *engine); 72 | void RegisterScriptAny_Generic(asIScriptEngine *engine); 73 | 74 | END_AS_NAMESPACE 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /src/AngelscriptUtilsTest/add_on/scriptarray/scriptarray.h: -------------------------------------------------------------------------------- 1 | #ifndef SCRIPTARRAY_H 2 | #define SCRIPTARRAY_H 3 | 4 | #ifndef ANGELSCRIPT_H 5 | // Avoid having to inform include path if header is already include before 6 | #include 7 | #endif 8 | 9 | // Sometimes it may be desired to use the same method names as used by C++ STL. 10 | // This may for example reduce time when converting code from script to C++ or 11 | // back. 12 | // 13 | // 0 = off 14 | // 1 = on 15 | 16 | #ifndef AS_USE_STLNAMES 17 | #define AS_USE_STLNAMES 0 18 | #endif 19 | 20 | BEGIN_AS_NAMESPACE 21 | 22 | struct SArrayBuffer; 23 | struct SArrayCache; 24 | 25 | class CScriptArray 26 | { 27 | public: 28 | // Set the memory functions that should be used by all CScriptArrays 29 | static void SetMemoryFunctions(asALLOCFUNC_t allocFunc, asFREEFUNC_t freeFunc); 30 | 31 | // Factory functions 32 | static CScriptArray *Create(asITypeInfo *ot); 33 | static CScriptArray *Create(asITypeInfo *ot, asUINT length); 34 | static CScriptArray *Create(asITypeInfo *ot, asUINT length, void *defaultValue); 35 | static CScriptArray *Create(asITypeInfo *ot, void *listBuffer); 36 | 37 | // Memory management 38 | void AddRef() const; 39 | void Release() const; 40 | 41 | // Type information 42 | asITypeInfo *GetArrayObjectType() const; 43 | int GetArrayTypeId() const; 44 | int GetElementTypeId() const; 45 | 46 | // Get the current size 47 | asUINT GetSize() const; 48 | 49 | // Returns true if the array is empty 50 | bool IsEmpty() const; 51 | 52 | // Pre-allocates memory for elements 53 | void Reserve(asUINT maxElements); 54 | 55 | // Resize the array 56 | void Resize(asUINT numElements); 57 | 58 | // Get a pointer to an element. Returns 0 if out of bounds 59 | void *At(asUINT index); 60 | const void *At(asUINT index) const; 61 | 62 | // Set value of an element. 63 | // The value arg should be a pointer to the value that will be copied to the element. 64 | // Remember, if the array holds handles the value parameter should be the 65 | // address of the handle. The refCount of the object will also be incremented 66 | void SetValue(asUINT index, void *value); 67 | 68 | // Copy the contents of one array to another (only if the types are the same) 69 | CScriptArray &operator=(const CScriptArray&); 70 | 71 | // Compare two arrays 72 | bool operator==(const CScriptArray &) const; 73 | 74 | // Array manipulation 75 | void InsertAt(asUINT index, void *value); 76 | void InsertAt(asUINT index, const CScriptArray &arr); 77 | void InsertLast(void *value); 78 | void RemoveAt(asUINT index); 79 | void RemoveLast(); 80 | void RemoveRange(asUINT start, asUINT count); 81 | void SortAsc(); 82 | void SortDesc(); 83 | void SortAsc(asUINT startAt, asUINT count); 84 | void SortDesc(asUINT startAt, asUINT count); 85 | void Sort(asUINT startAt, asUINT count, bool asc); 86 | void Sort(asIScriptFunction *less, asUINT startAt, asUINT count); 87 | void Reverse(); 88 | int Find(void *value) const; 89 | int Find(asUINT startAt, void *value) const; 90 | int FindByRef(void *ref) const; 91 | int FindByRef(asUINT startAt, void *ref) const; 92 | 93 | // Return the address of internal buffer for direct manipulation of elements 94 | void *GetBuffer(); 95 | 96 | // GC methods 97 | int GetRefCount(); 98 | void SetFlag(); 99 | bool GetFlag(); 100 | void EnumReferences(asIScriptEngine *engine); 101 | void ReleaseAllHandles(asIScriptEngine *engine); 102 | 103 | protected: 104 | mutable int refCount; 105 | mutable bool gcFlag; 106 | asITypeInfo *objType; 107 | SArrayBuffer *buffer; 108 | int elementSize; 109 | int subTypeId; 110 | 111 | // Constructors 112 | CScriptArray(asITypeInfo *ot, void *initBuf); // Called from script when initialized with list 113 | CScriptArray(asUINT length, asITypeInfo *ot); 114 | CScriptArray(asUINT length, void *defVal, asITypeInfo *ot); 115 | CScriptArray(const CScriptArray &other); 116 | virtual ~CScriptArray(); 117 | 118 | bool Less(const void *a, const void *b, bool asc, asIScriptContext *ctx, SArrayCache *cache); 119 | void *GetArrayItemPointer(int index); 120 | void *GetDataPointer(void *buffer); 121 | void Copy(void *dst, void *src); 122 | void Precache(); 123 | bool CheckMaxSize(asUINT numElements); 124 | void Resize(int delta, asUINT at); 125 | void CreateBuffer(SArrayBuffer **buf, asUINT numElements); 126 | void DeleteBuffer(SArrayBuffer *buf); 127 | void CopyBuffer(SArrayBuffer *dst, SArrayBuffer *src); 128 | void Construct(SArrayBuffer *buf, asUINT start, asUINT end); 129 | void Destruct(SArrayBuffer *buf, asUINT start, asUINT end); 130 | bool Equals(const void *a, const void *b, asIScriptContext *ctx, SArrayCache *cache) const; 131 | }; 132 | 133 | void RegisterScriptArray(asIScriptEngine *engine, bool defaultArray); 134 | 135 | END_AS_NAMESPACE 136 | 137 | #endif 138 | -------------------------------------------------------------------------------- /src/AngelscriptUtilsTest/add_on/scriptdictionary/scriptdictionary.h: -------------------------------------------------------------------------------- 1 | #ifndef SCRIPTDICTIONARY_H 2 | #define SCRIPTDICTIONARY_H 3 | 4 | // The dictionary class relies on the script string object, thus the script 5 | // string type must be registered with the engine before registering the 6 | // dictionary type 7 | 8 | #ifndef ANGELSCRIPT_H 9 | // Avoid having to inform include path if header is already include before 10 | #include 11 | #endif 12 | 13 | // By default the CScriptDictionary use the std::string for the keys. 14 | // If the application uses a custom string type, then this typedef 15 | // can be changed accordingly. Remember, if the application uses 16 | // a ref counted string type, then further changes will be needed, 17 | // for example in the code for GetKeys() and the constructor that 18 | // takes an initialization list. 19 | #include 20 | typedef std::string dictKey_t; 21 | 22 | // Forward declare CScriptDictValue so we can typedef the internal map type 23 | BEGIN_AS_NAMESPACE 24 | class CScriptDictValue; 25 | END_AS_NAMESPACE 26 | 27 | // C++11 introduced the std::unordered_map which is a hash map which is 28 | // is generally more performatic for lookups than the std::map which is a 29 | // binary tree. 30 | // TODO: memory: The map allocator should use the asAllocMem and asFreeMem 31 | #if AS_CAN_USE_CPP11 32 | #include 33 | typedef std::unordered_map dictMap_t; 34 | #else 35 | #include 36 | typedef std::map dictMap_t; 37 | #endif 38 | 39 | 40 | #ifdef _MSC_VER 41 | // Turn off annoying warnings about truncated symbol names 42 | #pragma warning (disable:4786) 43 | #endif 44 | 45 | 46 | 47 | 48 | // Sometimes it may be desired to use the same method names as used by C++ STL. 49 | // This may for example reduce time when converting code from script to C++ or 50 | // back. 51 | // 52 | // 0 = off 53 | // 1 = on 54 | 55 | #ifndef AS_USE_STLNAMES 56 | #define AS_USE_STLNAMES 0 57 | #endif 58 | 59 | 60 | BEGIN_AS_NAMESPACE 61 | 62 | class CScriptArray; 63 | class CScriptDictionary; 64 | 65 | class CScriptDictValue 66 | { 67 | public: 68 | // This class must not be declared as local variable in C++, because it needs 69 | // to receive the script engine pointer in all operations. The engine pointer 70 | // is not kept as member in order to keep the size down 71 | CScriptDictValue(); 72 | CScriptDictValue(asIScriptEngine *engine, void *value, int typeId); 73 | 74 | // Destructor must not be called without first calling FreeValue, otherwise a memory leak will occur 75 | ~CScriptDictValue(); 76 | 77 | // Replace the stored value 78 | void Set(asIScriptEngine *engine, void *value, int typeId); 79 | void Set(asIScriptEngine *engine, const asINT64 &value); 80 | void Set(asIScriptEngine *engine, const double &value); 81 | void Set(asIScriptEngine *engine, CScriptDictValue &value); 82 | 83 | // Gets the stored value. Returns false if the value isn't compatible with the informed typeId 84 | bool Get(asIScriptEngine *engine, void *value, int typeId) const; 85 | bool Get(asIScriptEngine *engine, asINT64 &value) const; 86 | bool Get(asIScriptEngine *engine, double &value) const; 87 | 88 | // Returns the address of the stored value for inspection 89 | const void *GetAddressOfValue() const; 90 | 91 | // Returns the type id of the stored value 92 | int GetTypeId() const; 93 | 94 | // Free the stored value 95 | void FreeValue(asIScriptEngine *engine); 96 | 97 | protected: 98 | friend class CScriptDictionary; 99 | 100 | union 101 | { 102 | asINT64 m_valueInt; 103 | double m_valueFlt; 104 | void *m_valueObj; 105 | }; 106 | int m_typeId; 107 | }; 108 | 109 | class CScriptDictionary 110 | { 111 | public: 112 | // Factory functions 113 | static CScriptDictionary *Create(asIScriptEngine *engine); 114 | 115 | // Called from the script to instantiate a dictionary from an initialization list 116 | static CScriptDictionary *Create(asBYTE *buffer); 117 | 118 | // Reference counting 119 | void AddRef() const; 120 | void Release() const; 121 | 122 | // Reassign the dictionary 123 | CScriptDictionary &operator =(const CScriptDictionary &other); 124 | 125 | // Sets a key/value pair 126 | void Set(const dictKey_t &key, void *value, int typeId); 127 | void Set(const dictKey_t &key, const asINT64 &value); 128 | void Set(const dictKey_t &key, const double &value); 129 | 130 | // Gets the stored value. Returns false if the value isn't compatible with the informed typeId 131 | bool Get(const dictKey_t &key, void *value, int typeId) const; 132 | bool Get(const dictKey_t &key, asINT64 &value) const; 133 | bool Get(const dictKey_t &key, double &value) const; 134 | 135 | // Index accessors. If the dictionary is not const it inserts the value if it doesn't already exist 136 | // If the dictionary is const then a script exception is set if it doesn't exist and a null pointer is returned 137 | CScriptDictValue *operator[](const dictKey_t &key); 138 | const CScriptDictValue *operator[](const dictKey_t &key) const; 139 | 140 | // Returns the type id of the stored value, or negative if it doesn't exist 141 | int GetTypeId(const dictKey_t &key) const; 142 | 143 | // Returns true if the key is set 144 | bool Exists(const dictKey_t &key) const; 145 | 146 | // Returns true if there are no key/value pairs in the dictionary 147 | bool IsEmpty() const; 148 | 149 | // Returns the number of key/value pairs in the dictionary 150 | asUINT GetSize() const; 151 | 152 | // Deletes the key 153 | bool Delete(const dictKey_t &key); 154 | 155 | // Deletes all keys 156 | void DeleteAll(); 157 | 158 | // Get an array of all keys 159 | CScriptArray *GetKeys() const; 160 | 161 | // STL style iterator 162 | class CIterator 163 | { 164 | public: 165 | void operator++(); // Pre-increment 166 | void operator++(int); // Post-increment 167 | 168 | // This is needed to support C++11 range-for 169 | CIterator &operator*(); 170 | 171 | bool operator==(const CIterator &other) const; 172 | bool operator!=(const CIterator &other) const; 173 | 174 | // Accessors 175 | const dictKey_t &GetKey() const; 176 | int GetTypeId() const; 177 | bool GetValue(asINT64 &value) const; 178 | bool GetValue(double &value) const; 179 | bool GetValue(void *value, int typeId) const; 180 | const void * GetAddressOfValue() const; 181 | 182 | protected: 183 | friend class CScriptDictionary; 184 | 185 | CIterator(); 186 | CIterator(const CScriptDictionary &dict, 187 | dictMap_t::const_iterator it); 188 | 189 | CIterator &operator=(const CIterator &) {return *this;} // Not used 190 | 191 | dictMap_t::const_iterator m_it; 192 | const CScriptDictionary &m_dict; 193 | }; 194 | 195 | CIterator begin() const; 196 | CIterator end() const; 197 | CIterator find(const dictKey_t &key) const; 198 | 199 | // Garbage collections behaviours 200 | int GetRefCount(); 201 | void SetGCFlag(); 202 | bool GetGCFlag(); 203 | void EnumReferences(asIScriptEngine *engine); 204 | void ReleaseAllReferences(asIScriptEngine *engine); 205 | 206 | protected: 207 | // Since the dictionary uses the asAllocMem and asFreeMem functions to allocate memory 208 | // the constructors are made protected so that the application cannot allocate it 209 | // manually in a different way 210 | CScriptDictionary(asIScriptEngine *engine); 211 | CScriptDictionary(asBYTE *buffer); 212 | 213 | // We don't want anyone to call the destructor directly, it should be called through the Release method 214 | virtual ~CScriptDictionary(); 215 | 216 | // Cache the object types needed 217 | void Init(asIScriptEngine *engine); 218 | 219 | // Our properties 220 | asIScriptEngine *engine; 221 | mutable int refCount; 222 | mutable bool gcFlag; 223 | dictMap_t dict; 224 | }; 225 | 226 | // This function will determine the configuration of the engine 227 | // and use one of the two functions below to register the dictionary object 228 | void RegisterScriptDictionary(asIScriptEngine *engine); 229 | 230 | // Call this function to register the math functions 231 | // using native calling conventions 232 | void RegisterScriptDictionary_Native(asIScriptEngine *engine); 233 | 234 | // Use this one instead if native calling conventions 235 | // are not supported on the target platform 236 | void RegisterScriptDictionary_Generic(asIScriptEngine *engine); 237 | 238 | END_AS_NAMESPACE 239 | 240 | #endif 241 | -------------------------------------------------------------------------------- /src/AngelscriptUtilsTest/add_on/scriptstdstring/scriptstdstring.h: -------------------------------------------------------------------------------- 1 | // 2 | // Script std::string 3 | // 4 | // This function registers the std::string type with AngelScript to be used as the default string type. 5 | // 6 | // The string type is registered as a value type, thus may have performance issues if a lot of 7 | // string operations are performed in the script. However, for relatively few operations, this should 8 | // not cause any problem for most applications. 9 | // 10 | 11 | #ifndef SCRIPTSTDSTRING_H 12 | #define SCRIPTSTDSTRING_H 13 | 14 | #ifndef ANGELSCRIPT_H 15 | // Avoid having to inform include path if header is already include before 16 | #include 17 | #endif 18 | 19 | #include 20 | 21 | //--------------------------- 22 | // Compilation settings 23 | // 24 | 25 | // Sometimes it may be desired to use the same method names as used by C++ STL. 26 | // This may for example reduce time when converting code from script to C++ or 27 | // back. 28 | // 29 | // 0 = off 30 | // 1 = on 31 | 32 | #ifndef AS_USE_STLNAMES 33 | #define AS_USE_STLNAMES 0 34 | #endif 35 | 36 | BEGIN_AS_NAMESPACE 37 | 38 | void RegisterStdString(asIScriptEngine *engine); 39 | void RegisterStdStringUtils(asIScriptEngine *engine); 40 | 41 | END_AS_NAMESPACE 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /src/AngelscriptUtilsTest/add_on/scriptstdstring/scriptstdstring_utils.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "scriptstdstring.h" 3 | #include "../scriptarray/scriptarray.h" 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | BEGIN_AS_NAMESPACE 10 | 11 | // This function takes an input string and splits it into parts by looking 12 | // for a specified delimiter. Example: 13 | // 14 | // string str = "A|B||D"; 15 | // array@ array = str.split("|"); 16 | // 17 | // The resulting array has the following elements: 18 | // 19 | // {"A", "B", "", "D"} 20 | // 21 | // AngelScript signature: 22 | // array@ string::split(const string &in delim) const 23 | static CScriptArray *StringSplit(const string &delim, const string &str) 24 | { 25 | // Obtain a pointer to the engine 26 | asIScriptContext *ctx = asGetActiveContext(); 27 | asIScriptEngine *engine = ctx->GetEngine(); 28 | 29 | // TODO: This should only be done once 30 | // TODO: This assumes that CScriptArray was already registered 31 | asITypeInfo *arrayType = engine->GetTypeInfoByDecl("array"); 32 | 33 | // Create the array object 34 | CScriptArray *array = CScriptArray::Create(arrayType); 35 | 36 | // Find the existence of the delimiter in the input string 37 | int pos = 0, prev = 0, count = 0; 38 | while( (pos = (int)str.find(delim, prev)) != (int)string::npos ) 39 | { 40 | // Add the part to the array 41 | array->Resize(array->GetSize()+1); 42 | ((string*)array->At(count))->assign(&str[prev], pos-prev); 43 | 44 | // Find the next part 45 | count++; 46 | prev = pos + (int)delim.length(); 47 | } 48 | 49 | // Add the remaining part 50 | array->Resize(array->GetSize()+1); 51 | ((string*)array->At(count))->assign(&str[prev]); 52 | 53 | return array; 54 | } 55 | 56 | static void StringSplit_Generic(asIScriptGeneric *gen) 57 | { 58 | // Get the arguments 59 | string *str = (string*)gen->GetObject(); 60 | string *delim = *(string**)gen->GetAddressOfArg(0); 61 | 62 | // Return the array by handle 63 | *(CScriptArray**)gen->GetAddressOfReturnLocation() = StringSplit(*delim, *str); 64 | } 65 | 66 | 67 | 68 | // This function takes as input an array of string handles as well as a 69 | // delimiter and concatenates the array elements into one delimited string. 70 | // Example: 71 | // 72 | // array array = {"A", "B", "", "D"}; 73 | // string str = join(array, "|"); 74 | // 75 | // The resulting string is: 76 | // 77 | // "A|B||D" 78 | // 79 | // AngelScript signature: 80 | // string join(const array &in array, const string &in delim) 81 | static string StringJoin(const CScriptArray &array, const string &delim) 82 | { 83 | // Create the new string 84 | string str = ""; 85 | if( array.GetSize() ) 86 | { 87 | int n; 88 | for( n = 0; n < (int)array.GetSize() - 1; n++ ) 89 | { 90 | str += *(string*)array.At(n); 91 | str += delim; 92 | } 93 | 94 | // Add the last part 95 | str += *(string*)array.At(n); 96 | } 97 | 98 | return str; 99 | } 100 | 101 | static void StringJoin_Generic(asIScriptGeneric *gen) 102 | { 103 | // Get the arguments 104 | CScriptArray *array = *(CScriptArray**)gen->GetAddressOfArg(0); 105 | string *delim = *(string**)gen->GetAddressOfArg(1); 106 | 107 | // Return the string 108 | new(gen->GetAddressOfReturnLocation()) string(StringJoin(*array, *delim)); 109 | } 110 | 111 | // This is where the utility functions are registered. 112 | // The string type must have been registered first. 113 | void RegisterStdStringUtils(asIScriptEngine *engine) 114 | { 115 | int r; 116 | 117 | if( strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY") ) 118 | { 119 | r = engine->RegisterObjectMethod("string", "array@ split(const string &in) const", asFUNCTION(StringSplit_Generic), asCALL_GENERIC); assert(r >= 0); 120 | r = engine->RegisterGlobalFunction("string join(const array &in, const string &in)", asFUNCTION(StringJoin_Generic), asCALL_GENERIC); assert(r >= 0); 121 | } 122 | else 123 | { 124 | r = engine->RegisterObjectMethod("string", "array@ split(const string &in) const", asFUNCTION(StringSplit), asCALL_CDECL_OBJLAST); assert(r >= 0); 125 | r = engine->RegisterGlobalFunction("string join(const array &in, const string &in)", asFUNCTION(StringJoin), asCALL_CDECL); assert(r >= 0); 126 | } 127 | } 128 | 129 | END_AS_NAMESPACE 130 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory( AngelscriptUtils ) 2 | add_subdirectory( AngelscriptUtilsTest ) 3 | --------------------------------------------------------------------------------